1,222
社区成员




//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <mmsystem.h>
#include <Menus.hpp>
#include <ComCtrls.hpp>
#include <Graphics.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *btSave;
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
void __fastcall btSaveClick(TObject *Sender);
private: // User declarations
bool bRecordingStarted;
HWAVEIN hWaveIn;
WAVEHDR* WaveHeaders; ///< pointer to allocated table of headers
WAVEFORMATEX waveFormat;
int iBuffIdx; ///< index of next buffer available for recording
int iBuffersCount; ///< total buffer count for audio data
int iSamplesPerChannel; ///< samples per channels count (in buffer)
int WaveBufSize;
WAVEHDR* SendHeader;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
void __fastcall ProcessSamples();
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
iBuffersCount = 4; // uses double-buffering
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include<iostream>
#include<math.h>
#include<stdio.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
TMemoryStream* pms;
struct RIFF_HEADER//文件类型
{
char szRiffID[4]; // 'R','I','F','F'
DWORD dwRiffSize;//DWORD最大可容纳4GB的文件大小=FILE_LENGTH-8(即减去此数据结构大小)
char szRiffFormat[4]; // 'W','A','V','E'
};
struct WAVE_FORMAT
{
WORD wFormatTag;
WORD wChannels;
DWORD dwSamplesPerSec;
DWORD dwAvgBytesPerSec;
WORD wBlockAlign;
WORD wBitsPerSample;
};
struct FMT_BLOCK//格式
{
char szFmtID[4]; // 'f','m','t',' '
DWORD dwFmtSize;//////////////一般情况下为16,如有附加信息为18
WAVE_FORMAT wavFormat;
};
struct FACT_BLOCK//可先项 一般可不用
{
char szFactID[4]; // 'f','a','c','t'
DWORD dwFactSize;
};
struct DATA_BLOCK//数据头
{
char szDataID[4]; // 'd','a','t','a'
DWORD dwDataSize;//数据长度
};
//---------------------------------------------------------------------------
void CALLBACK WaveInProc(HWAVEIN waveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2)
{
if ( uMsg == MM_WIM_DATA )
{
WAVEHDR * in = (WAVEHDR *)dwParam1;
int buf_len= in->dwBytesRecorded;
pms->Write(in->lpData,buf_len);
Form1->ProcessSamples();
}
}
void __fastcall TForm1::ProcessSamples()
{
//
// Prepare data buffer
//
if ( bRecordingStarted )
{
WAVEHDR *in = &WaveHeaders[iBuffIdx];
::waveInUnprepareHeader( hWaveIn, in, sizeof(WAVEHDR) );
// next buffer to send
iBuffIdx++;
if ( iBuffIdx == iBuffersCount )
iBuffIdx=0;
SendHeader->dwBufferLength=WaveBufSize;
SendHeader->dwFlags=0;
SendHeader->dwLoops=0;
::waveInPrepareHeader( hWaveIn, SendHeader, sizeof(WAVEHDR) );
::waveInAddBuffer( hWaveIn, SendHeader, sizeof(WAVEHDR));
if ( SendHeader == &WaveHeaders[iBuffersCount-1] )
SendHeader = &WaveHeaders[0];
else
SendHeader++;
}
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
iBuffersCount = 2; // uses double-buffering
iSamplesPerChannel = 1024; ///< total samples count (per channel)
iBuffIdx = 0;
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nChannels = 2;
waveFormat.nSamplesPerSec = 44100;// 44100;
waveFormat.wBitsPerSample = 16;
waveFormat.nBlockAlign = waveFormat.wBitsPerSample/8*waveFormat.nChannels;
waveFormat.nAvgBytesPerSec = waveFormat.nBlockAlign*waveFormat.nSamplesPerSec;
waveFormat.cbSize = 0;
pms = new TMemoryStream();
pms->Position = 0;
// Audio buffers
WaveHeaders = new WAVEHDR[iBuffersCount];
WaveBufSize = iSamplesPerChannel * (waveFormat.wBitsPerSample/8) * waveFormat.nChannels;
for ( int i = 0; i<iBuffersCount; i++ )
{
WaveHeaders[i].dwBufferLength = WaveBufSize;
WaveHeaders[i].lpData = (char *)VirtualAlloc( 0, WaveBufSize, MEM_COMMIT, PAGE_READWRITE );
}
if ( waveInOpen( &hWaveIn, WAVE_MAPPER, &waveFormat, (DWORD)WaveInProc, (DWORD)this, CALLBACK_FUNCTION ) == MMSYSERR_NOERROR)
{
for ( int i = 0; i<iBuffersCount/2; i++ )
{
WaveHeaders[i].dwBufferLength=WaveBufSize;
WaveHeaders[i].dwFlags=0;
WaveHeaders[i].dwLoops=0;
if ( waveInPrepareHeader( hWaveIn, &WaveHeaders[i], sizeof(WAVEHDR))== MMSYSERR_NOERROR)
if ( waveInAddBuffer( hWaveIn, &WaveHeaders[i], sizeof(WAVEHDR))!= MMSYSERR_NOERROR)
{
Application->MessageBox("Error opening audio device."
"Check if device is capable of recording with selected parameters or isn't busy.\n",
this->Caption.c_str(), MB_ICONEXCLAMATION);
Application->Terminate();
}
}
if ( waveInStart( hWaveIn ) == MMSYSERR_NOERROR )
{
SendHeader = &WaveHeaders[iBuffersCount/2];
iBuffIdx = 0;
bRecordingStarted = true;
}
else
{
Application->MessageBox( "Error", "Multimedia Error", MB_OK);
Application->Terminate();
}
}
else
{
Application->MessageBox( "Error", "Multimedia Error", MB_OK);
Application->Terminate();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
waveInStop(hWaveIn);
bRecordingStarted = false;
MMRESULT res=waveInReset( hWaveIn );
for ( int i = 0; i<iBuffersCount; i++ )
{
res = ::waveInUnprepareHeader( hWaveIn, &WaveHeaders[i], sizeof(WAVEHDR) );
while ( res == WAVERR_STILLPLAYING )
{
// The buffer pointed to by the pwh parameter is still in the queue.
Sleep( 50 );
res = ::waveInUnprepareHeader( hWaveIn, &WaveHeaders[i], sizeof(WAVEHDR) );
}
}
::waveInClose( hWaveIn );
delete pms;
for ( int i=0; i<iBuffersCount; i++ )
VirtualFree( WaveHeaders[i].lpData, 0, MEM_RELEASE );
delete [] WaveHeaders;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btSaveClick(TObject *Sender)
{
RIFF_HEADER riff;
WAVE_FORMAT wform;
FMT_BLOCK fmt;
FACT_BLOCK fact;
DATA_BLOCK data;
waveInStop(hWaveIn);
bRecordingStarted = false;
//pms->Seek(0,soFromBeginning) ;
pms->Position = 0;
//pms->SaveToFile("wave.dat");
fmt.wavFormat.wFormatTag=WAVE_FORMAT_PCM;//1
fmt.wavFormat.dwAvgBytesPerSec=waveFormat.nAvgBytesPerSec;
fmt.wavFormat.dwSamplesPerSec=waveFormat.nSamplesPerSec;
fmt.wavFormat.wBitsPerSample=waveFormat.wBitsPerSample;
fmt.wavFormat.wBlockAlign=waveFormat.nBlockAlign;
fmt.wavFormat.wChannels=waveFormat.nChannels;
sprintf(fmt.szFmtID,"%s","fmt ");
fmt.dwFmtSize=16;//一般情况下为16,如有附加信息为18
sprintf(data.szDataID,"%s","data");
data.dwDataSize=pms->Size;
riff.dwRiffSize=pms->Size+sizeof(FMT_BLOCK)+sizeof(DATA_BLOCK);
strncpy(riff.szRiffFormat,"WAVE",4);
sprintf(riff.szRiffID,"%s","RIFF");
FILE* file=fopen("rec.wav","wb");
fwrite(&riff,sizeof(RIFF_HEADER),1,file);//写RIFF_HEADER
fwrite(&fmt,sizeof(FMT_BLOCK),1,file);//写FMT_BLOCK
fwrite(&data,sizeof(DATA_BLOCK),1,file);//写数据头 DATA_BLOCK
fwrite(pms->Memory,sizeof(BYTE),pms->Size,file);//写音频数据
fclose(file);
}
//---------------------------------------------------------------------------