一個是視頻的,一個關於語音的,都是網上收集到的.源代碼

一個是視頻的,一個關於語音的,都是網上收集到的.源代碼

#pragma hdrstop

#include "Unit1.h"
#include "vfw.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
HWND hWndC;
CAPDRIVERCAPS CapDrvCaps;
CAPSTATUS CapStatus;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormShow(TObject *Sender)
{
    char szDeviceName[80];
    char szDeviceVersion[80];

    for (int wIndex = 0; wIndex < 10; wIndex++)
    {
        if (capGetDriverDescription (wIndex, szDeviceName,
            sizeof (szDeviceName), szDeviceVersion,
            sizeof (szDeviceVersion)))
        {
            ComboBox1->Items->Add(szDeviceName);
        }
    }
   
    if(ComboBox1->Items->Count>0)
        ComboBox1->ItemIndex=0;
    else
    {
        ShowMessage("沒有找到視頻軟件");
        Close();
    }
    Button1Click(NULL);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    hWndC = capCreateCaptureWindow (
        (LPSTR) "My Capture Window", // window name if pop-up
        WS_CHILD | WS_VISIBLE, // window style
        0, 0, 160, 120, // window position and dimensions
        (HWND)Panel2->Handle,//(HWND)Application->Handle,//(HWND) hwndParent,
        ComboBox1->ItemIndex+1);//(int) nID /* child ID */);

    //連接設備:
    capDriverConnect(hWndC,0);
    capPreviewRate(hWndC, 50); // rate, in milliseconds
    capPreview(hWndC, TRUE); // starts preview

    //獲取視頻驅動相關性能
    capDriverGetCaps(hWndC, &CapDrvCaps, sizeof (CAPDRIVERCAPS));

    //獲取捕獲窗口狀態
    capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));
    SetWindowPos(hWndC, NULL,
        0,
        0,
        CapStatus.uiImageWidth,
        CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
    if(hWndC)
    {
        capPreview(hWndC, FALSE); // starts preview
        capDriverDisconnect (hWndC);
    }
}
//---------------------------------------------------------------------------


void __fastcall TForm1::Button2Click(TObject *Sender)
{
    // Video format dialog box.
    if (CapDrvCaps.fHasDlgVideoFormat)
    {
        capDlgVideoFormat(hWndC);
        // Are there new image dimensions?
        capGetStatus(hWndC, &CapStatus, sizeof (CAPSTATUS));
        SetWindowPos(hWndC, NULL,
            0,
            0,
            CapStatus.uiImageWidth,
            CapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE);
    }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)
{
    // Video source dialog box.
    if (CapDrvCaps.fHasDlgVideoSource)
        capDlgVideoSource(hWndC);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button4Click(TObject *Sender)
{
    //設置相關參數
    CAPTUREPARMS CaptureParms;
    float FramesPerSec = 30.0;

    capCaptureGetSetup(hWndC, &CaptureParms, sizeof(CAPTUREPARMS));

    CaptureParms.dwRequestMicroSecPerFrame = (DWORD) (1.0e6 /
        FramesPerSec);
    capCaptureSetSetup(hWndC, &CaptureParms, sizeof (CAPTUREPARMS));
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button5Click(TObject *Sender)
{
    //設置預覽時的比例
    capPreviewScale(hWndC, 1);
    //設置預覽時的幀頻率
    capPreviewRate(hWndC,66);
    //如果要捕獲視頻流,則要使用函數指定不生成文件。否則將會自動生成AVI文件
    capCaptureSequenceNoFile(hWndC);
    //指定是否使用疊加模式,使用爲1,否則爲0
    capOverlay(hWndC, 1);
   
    //Video display dialog box.
    if (CapDrvCaps.fHasDlgVideoDisplay)
        capDlgVideoDisplay(hWndC);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button6Click(TObject *Sender)
{
    if(SaveDialog2->Execute())
        capFileSaveDIB( hWndC, (SaveDialog2->FileName+".bmp").c_str() ); //截取當前幀
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button7Click(TObject *Sender)
{
    if(Button7->Caption == "開始捕獲")
    {
        if(SaveDialog1->Execute())
        {
            // Set up the capture operation.
            capCaptureSequence(hWndC);
            // Capture.
            capFileSaveAs(hWndC, (SaveDialog1->FileName+".avi").c_str());//視頻
        }
        Button7->Caption="停止捕獲";
    }
    else
    {
        Button7->Caption="開始捕獲";
        capCaptureStop(hWndC);
    }
}
//------------------------------------------------------------------------------------------------------------------------

1.語音的採集和播放。
  本軟件中要把語音直接轉換爲數據,放在內存中,而不是存爲語音文件,而且播放語音時,也是直接播放語音數據,而不是播放語音文件。這樣的好處前面已經提到,即省略了讀寫硬盤的費時操作,提高了語音通話的實時性。
  要完成上述語音操作,編程語言中提供的容易使用的高級的多媒體語音函數是無法勝任的,只能用一些底層的語音函數來實現,這一類函數和結構的名字都以"wave"作爲前綴。
  下面簡要分析錄音和放音的流程,考慮到兩着的處理和流程基本上是類似的,本文就只以錄音爲例來分析,如圖三爲錄音流程。錄音的準備工作主要是三點,打開錄音設備,獲得錄音句柄,指定錄音格式,分配若干用於錄音的內存,內存的大小和數量下文將進一步分析。開始錄音時,先將所有內存塊都提供給錄音設備用來錄音,錄音設備就會依次將語音數據寫入內存,當一塊內存寫滿,錄音設備就會發一個Window 消息MM_WIM_DATA給相應的窗口,通知程序作相關的處理,這時程序通常的處理是把內存中的數據進行復制,如寫入文件等,在此我們的處理是把數據進行壓縮和網絡發送,然後把內存置空,返還給錄音設備進行錄音,這樣就形成一個循環不息的錄音過程。結束錄音時就釋放所有內存塊,關閉錄音設備。

錄音流程 

以錄音爲例,關鍵的錄音函數和順序如下:
WAVEFORMATEX waveformat;
waveformat.wFormatTag=WAVE_FORMAT_PCM;
waveformat.nChannels=1;
waveformat.nSamplesPerSec=8000;
waveformat.nAvgBytesPerSec=16000;
waveformat.nBlockAlign=2;
waveformat.cbSize=0;
waveformat.wBitsPerSample=16; //指定錄音格式
int res=waveInOpen(&m_hWaveIn,WAVE_MAPPER, &waveformat, (DWORD)m_hWnd,0L,CALLBACK_WINDOW); //打開錄音設備
waveInPrepareHeader(m_hWaveIn,m_pWaveHdr[i],sizeof(WAVEHDR)); //準備內存塊錄音
waveInAddBuffer(m_hWaveIn,m_pWaveHdr[i],sizeof(WAVEHDR)); //增加內存塊
waveInStart(m_hWaveIn);//開始錄音
waveInStop(m_hWaveIn); //停止錄音
waveInReset(m_hWaveIn); //清空內存塊
waveInClose(m_hWaveIn); //關閉錄音設備

完整源代碼
WaveInput.h
#ifndef WaveInputH
#define WaveInputH
#include
//----------

LPWAVEHDR AllocateInputLPWAVEHDRMemory(UINT size);
void FreeInPutBuffer(HWAVEIN hwi,LPWAVEHDR pwh);
//------------------
#endif


WaveInput.cpp
#include
#pragma hdrstop
#include "WaveInput.h"
//-------------------------------------------------------------------
LPWAVEHDR AllocateInputLPWAVEHDRMemory(UINT size)
{HPSTR sublpData;
HGLOBAL lpmemory;
LPWAVEHDR lpInWaveHdr;
lpmemory=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,size);
if(lpmemory==NULL)
ShowMessage("Failed to GloabalAlloc memory for data sublpData");
if((sublpData=(HPSTR)GlobalLock(lpmemory))==NULL)
{::MessageBox(0,"Failed to lock memory for data sublpData",NULL,MB_OK|MB_ICONEXCLAMATION);
}
lpmemory=GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,(DWORD)sizeof(WAVEHDR));
if(lpmemory==NULL)ShowMessage("Failed to globalAlloc memory for data LPWAVEHDR");
lpInWaveHdr=(LPWAVEHDR)GlobalLock(lpmemory);
if(lpInWaveHdr==NULL)
{::MessageBox(0,"failed to lock memory for header:lplpInWaveHdr",NULL,MB_OK|MB_ICONEXCLAMATION);
}
lpInWaveHdr->lpData=sublpData;
lpInWaveHdr->dwBufferLength=size;
lpInWaveHdr->dwLoops=0L;
lpInWaveHdr->dwFlags=0L;
sublpData=NULL;
lpmemory=NULL;
return(lpInWaveHdr);
}
//--------------------------
void FreeInPutBuffer(HWAVEIN hwi,LPWAVEHDR pwh)
{
if(waveInUnprepareHeader(hwi,pwh,sizeof(WAVEHDR))!=MMSYSERR_NOERROR)
ShowMessage("WaveInUnperpareHeader ERROR!");
try
{
delete pwh->lpData;
delete pwh;
}
catch(...)
{ShowMessage("delete pwh error!");
}
}
//----------------------------------------

WaveOutput.h

#ifndef WaveOutPutH
#define WaveOutPutH
#include
//-----------------------
LPWAVEHDR AllocateOutPutLPWAVEHDRMemory(HWAVEOUT phwo,UINT size);
void FreeOutPutBuffer(HWAVEOUT hwo,LPWAVEHDR pwh);
//----------------------------
#endif


WaveOutPut.cpp
#include
#pragma hdrstop
#include "WaveOutPut.h"
//------------------------
LPWAVEHDR AllocateOutPutLPWAVEHDRMemory(HWAVEOUT phwo,UINT size)
{
LPWAVEHDR lpOutWaveHdr;
lpOutWaveHdr=(LPWAVEHDR)GlobalLock(GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,sizeof(WAVEHDR)));
if(lpOutWaveHdr==NULL)
::MessageBox(0,"Failed to lock memory for header",NULL ,MB_OK|MB_ICONEXCLAMATION);
if((lpOutWaveHdr->lpData=(HPSTR)GlobalLock(GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,size)))==NULL)
::MessageBox(0,"Failed to lock memory for data chumk",NULL,MB_OK|MB_ICONEXCLAMATION);
lpOutWaveHdr->dwBufferLength=size;
lpOutWaveHdr->dwFlags=0L;
lpOutWaveHdr->dwLoops=0L;
waveOutPrepareHeader(phwo,lpOutWaveHdr,sizeof(WAVEHDR));
return(lpOutWaveHdr);
}
//---------------------------------------------------------------------
void FreeOutPutBuffer(HWAVEOUT hwo,LPWAVEHDR pwh)
{
switch(waveOutUnprepareHeader(hwo,pwh,sizeof(WAVEHDR)))
{case MMSYSERR_INVALHANDLE:
ShowMessage("MMSYSERR_INVALHANDLE");return;
case MMSYSERR_NODRIVER:
ShowMessage("MMSYSERR_NODRIVE");return;
case MMSYSERR_NOMEM:
ShowMessage("MMSYSERR_NOMEM");return;
case WAVERR_STILLPLAYING:
ShowMessage("WAVERR_STILLPLAYING");return;
}
try{
delete pwh->lpData;
delete pwh;
}
catch(...)
{ShowMessage("delete 'pwh'error!");
}
}


NetTelMain.h
//---------------------------------------------------------------------------

#ifndef NetTelMainH
#define NetTelMainH
//---------------------------------------------------------------------------
#define NETTEL_PORT 2001
//---------------------------------------------------------------------------
class TNetTelForm : public TForm
{
__published: // IDE-managed Components
TServerSocket *ServerSocket1;
TClientSocket *ClientSocket1;
TMainMenu *MainMenu1;
TLabel *Label_IP;
TEdit *Edit_IP;
TPanel *Panel1;
TGroupBox *VolumeGroupBox;
TTrackBar *VolumeBar;
TStatusBar *StatusBar1;
TMenuItem *N1;
TMenuItem *N2;
TMenuItem *N3;
TMenuItem *N4;
TMenuItem *N5;
TMenuItem *N6;
TMenuItem *N7;
void __fastcall ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket);
void __fastcall N2Click(TObject *Sender);
void __fastcall N3Click(TObject *Sender);
void __fastcall N4Click(TObject *Sender);
void __fastcall N5Click(TObject *Sender);
void __fastcall N6Click(TObject *Sender);
void __fastcall VolumeBarChange(TObject *Sender);
private:
WAVEFORMATEX pcmWaveFormat;
HWAVEIN phwi;
LPWAVEHDR lpInWaveHdr[2];
bool IsNeedSwap,IsPaused,WhichToPlay,OutputDeviceUnOpend;
HWAVEOUT pwho;
LPWAVEHDR lpOutWaveHdr[2];
DWORD Volume;
long MsgNumber,timebegin,timeend;
int getwhichtime,ReceiveLength;
void _fastcall InitializeOutputDevice();
void _fastcall CallBackPlay(TMessage*Message);
void _fastcall InitializeInputDevice();

public:

BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(MM_WIM_DATA,TMessage* ,CallBackPlay)
END_MESSAGE_MAP(TComponent)
__fastcall TNetTelForm(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TNetTelForm *NetTelForm;
//---------------------------------------------------------------------------
#endif
NetTelMain.cpp
//---------------------------------------------------------------------------

#include
#pragma hdrstop

#include "NetTelMain.h"
#include "WaveInput.h"
#include "WaveOutPut.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TNetTelForm *NetTelForm;
//---------------------------------------------------------------------------
__fastcall TNetTelForm::TNetTelForm(TComponent* Owner)
: TForm(Owner)
{
IsNeedSwap=true;
IsPaused=true;
WhichToPlay=true;
OutputDeviceUnOpend=true;
getwhichtime=0;
timebegin=timeend=0;
MsgNumber=0;
ReceiveLength=0;
InitializeInputDevice();
ServerSocket1->Port=2001;
ServerSocket1->Active=true;

}
//---------------------------------------------------------------------------
void _fastcall TNetTelForm::InitializeInputDevice()
{
//set up pcm wave format for 11 kHz 8-bit mono.
pcmWaveFormat.wFormatTag=WAVE_FORMAT_PCM;
pcmWaveFormat.nChannels=1;
pcmWaveFormat.nSamplesPerSec=11025L;
pcmWaveFormat.nAvgBytesPerSec=11025L;
pcmWaveFormat.nBlockAlign=1;
pcmWaveFormat.wBitsPerSample=8;
pcmWaveFormat.cbSize=0;
//open the output device

switch(waveInOpen(&phwi,WAVE_MAPPER,&pcmWaveFormat,(unsigned long)Handle,0,CALLBACK_WINDOW))
{ case MMSYSERR_ALLOCATED:
ShowMessage("MMSYSERR_ALLOCTEC");return;
case MMSYSERR_BADDEVICEID:
ShowMessage("MMSYSERR_BADDEVICEID");return;
case MMSYSERR_NODRIVER:
ShowMessage("MMSYSERR_NODRIVER");return;
case WAVERR_STILLPLAYING:
ShowMessage("WAVERR_STILLPLAYING");return;
case WAVERR_BADFORMAT:
ShowMessage("WAVERR_BADFORMAT");return;
}
// ALLOCATE MEMORY AND PERPARE FOR RECORDING
for(int i=0;i<=1;i++)
{lpInWaveHdr[i]=AllocateInputLPWAVEHDRMemory(4*1024);
switch(waveInPrepareHeader(phwi,lpInWaveHdr[i],sizeof(WAVEHDR)))
{case MMSYSERR_INVALHANDLE:
ShowMessage("MMSYSERR_INVALHANDLE");return;
case MMSYSERR_NODRIVER:
ShowMessage("MMSYSERR_NODRIVER");return;
case MMSYSERR_NOMEM:
ShowMessage("MMSYSERR_NOMEM");return;
}
}
switch(waveInAddBuffer(phwi,lpInWaveHdr[!IsNeedSwap],sizeof(WAVEHDR)))

{case MMSYSERR_INVALHANDLE:
ShowMessage("MMSYSERR_INVALHANDLE");return;
case MMSYSERR_NODRIVER:
ShowMessage("MMSYSERR_NODRIVER");return;
case MMSYSERR_NOMEM:
ShowMessage("MMSYSERR_NOMEM");return;
case WAVERR_UNPREPARED:
ShowMessage("WAVE_UNPREPAPERD");return;
}

}
//------------------------------------------------
void _fastcall TNetTelForm::CallBackPlay(TMessage *Message)
{
switch(waveInAddBuffer(phwi,lpInWaveHdr[!IsNeedSwap],sizeof(WAVEHDR)))
{ case WAVERR_UNPREPARED:
ShowMessage("WAVE_UNPREPAPERD");return;
case MMSYSERR_INVALHANDLE:
ShowMessage("MMSYSERR_INVALHANDLE");return;
case MMSYSERR_NODRIVER:
ShowMessage("MMSYSERR_NODRIVER");return;
case MMSYSERR_NOMEM:
ShowMessage("MMSYSERR_NOMEM");return;
}
ClientSocket1->Socket->SendBuf(lpInWaveHdr[!IsNeedSwap]->lpData,lpInWaveHdr[!IsNeedSwap]->dwBufferLength);
IsNeedSwap=!IsNeedSwap;
}
//------------------------
void _fastcall TNetTelForm::InitializeOutputDevice()
{if(waveOutOpen(&pwho,WAVE_MAPPER,&pcmWaveFormat,(unsigned long)Handle,0,CALLBACK_WINDOW)!=MMSYSERR_NOERROR)
::MessageBox(0,"out Open error","",MB_OK);
for(int i=0;i<=1;i++)
lpOutWaveHdr[i]=AllocateOutPutLPWAVEHDRMemory(pwho,4*1024);
Volume=Volume&0x00000000;
Volume=Volume^((DWORD)0xFFFF/2);
Volume=Volume^(((DWORD)0xFFFF/2)<<16);
if(waveOutSetVolume(pwho,Volume)!=MMSYSERR_NOERROR)
ShowMessage("waveOutSetVolume error!");
}

void __fastcall TNetTelForm::ServerSocket1ClientRead(TObject *Sender,
TCustomWinSocket *Socket)
{
if(OutputDeviceUnOpend)
{ InitializeOutputDevice();
OutputDeviceUnOpend=false;
}
try{ReceiveLength=Socket->ReceiveLength();
Socket->ReceiveBuf(lpOutWaveHdr[WhichToPlay]->lpData,ReceiveLength);
StatusBar1->Panels->Items[1]->Text=AnsiString("Packages:")+MsgNumber++;
if(waveOutWrite(pwho,lpOutWaveHdr[WhichToPlay],sizeof(WAVEHDR))==MMSYSERR_NOERROR)
StatusBar1->Panels->Items[0]->Text=AnsiString("Status:")+(int)WhichToPlay;
StatusBar1->Panels->Items[2]->Text=AnsiString("PSize:")+ReceiveLength;
WhichToPlay=!WhichToPlay;}
catch(...)
{StatusBar1->Panels->Items[0]->Text="WaveOut ERRor";}
}
//---------------------------------------------------------------------------

void __fastcall TNetTelForm::ConnectClick(TObject *Sender)
{
ClientSocket1->Active=false;
ClientSocket1->Address=Edit_IP->Text;
ClientSocket1->Port=2001;
ClientSocket1->Active=true;
}
//---------------------------------------------------------------------------

void __fastcall TNetTelForm::StartClick(TObject *Sender)
{
IsPaused=false;
waveInStart(phwi);
}
//---------------------------------------------------------------------------

void __fastcall TNetTelForm::PauseClick(TObject *Sender)
{
if(!IsPaused)
waveInStop(phwi);
}
//---------------------------------------------------------------------------

void __fastcall TNetTelForm::ResumeClick(TObject *Sender)
{
waveInStart(phwi);
}
//---------------------------------------------------------------------------

void __fastcall TNetTelForm::StopClick(TObject *Sender)
{
ServerSocket1->Active=false;
ClientSocket1->Active=false;
IsPaused=true;
waveInReset(phwi);
waveInStop(phwi);
for(int i=0;i<=1;i++) FreeInPutBuffer(phwi,lpInWaveHdr[i]);
waveInClose(phwi);
waveOutReset(pwho);
waveOutBreakLoop(pwho);
for(int i=0;i<=1;i++)FreeOutPutBuffer(pwho,lpOutWaveHdr[i]);
waveOutClose(pwho);
StatusBar1->Panels->Items[0]->Text="Is Stoped";
}
//---------------------------------------------------------------------------

void __fastcall TNetTelForm::VolumeBarChange(TObject *Sender)
{
Volume=Volume&0x00000000;
Volume=Volume^((DWORD)VolumeBar->Position*0xFFFF/100);
Volume=Volume^((DWORD)VolumeBar->Position*0xFFFF/100<<16);
if(waveOutSetVolume(pwho,Volume)!=MMSYSERR_NOERROR)
ShowMessage("waveoutsetvolumeerror");
}
//---------------------------------------------------------------------------

void __fastcall TNetTelForm::ExitClick(TObject *Sender)
{ if(!IsPaused)
{StopClick(Sender);}
Close();
}

void __fastcall TNetTelForm::FormDestroy(TObject *Sender)
{ExitClick(Sender);
}

void __fastcall TNetTelForm::TerminatedClick(TObject *Sender)
{ delete &phwi;
ExitClick(Sender);
TerminateProcess(GetCurrentProcess(),THREAD_SUSPEND_RESUME);
}

void __fastcall TNetTelForm::ClientSocket1Connect(TObject *Sender,TCustomWinSocket *Socket)
{StatusBar1->Panels-Items[0]->Text="Connect OK!";}

void __fastcall TNetTelForm::ClientSocket1Error(TObject *Sender,TCustomWinSocket *Socket,TErrorEvent ErrorEvent,int &ErrorCode)
{Socket->Close();}

void __fastcall TNetTelForm::ServerSocket1Error(TObject *Sender,TCustomWinSocket *Socket,TErrorEvent ErrorEvent,int &ErrorCode)
{Socket->Close();}
語音傳輸設置
爲了減少語音延遲,語音抖動,提高壓縮比.設置如下:
聲音源 採樣率爲22.050KHZ,16位,單聲道.
22.050*2*1=44.1KB/S
語音延遲最佳爲0.1秒,所以內存緩存大小爲4-5KB
提高壓縮比:錄製45.5秒的聲音大小爲1960KB
在C466,64MB採用解霸2000,22.050KHZ,128千位/S,用了14秒,mp3大小爲709KB.
爲了及時壓縮需要P2-233MHZ系統,10MB網絡

 

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/hangke/archive/2008/02/19/2107069.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章