用API录音保存到wav文件的问题,各位高手请进来看下

lihuimin622 2010-09-06 03:17:53
程序已经实现录音并保存到wav文件,现在的问题是录音文件回放的时候有点杂音,声音好像有点波动,不知道是哪个环节出了问题。可以排除话筒等硬件设备的问题,因为我用windows的录音机试过,是没问题的。现贴出代码,高手帮忙分析一下。
程序运行开始录音,按保存按钮保存到wav文件。
unit1.h



//---------------------------------------------------------------------------

#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
...全文
443 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
ccrun.com 2010-09-06
  • 打赏
  • 举报
回复
耶喝。
zzbinfo 2010-09-06
  • 打赏
  • 举报
回复
应该是数据量大,两个缓冲不够用吧,漏了数据了,所以听到的就有噪音了。
lihuimin622 2010-09-06
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 zzbinfo 的回复:]
增加你的缓冲区个数,测试了一下,效果还是很不错的。

C/C++ code
iBuffersCount = 4; // uses double-buffering
[/Quote]

太感谢了,这样改一下果然没问题了,怎么iBuffersCount = 2就不行呢?
zzbinfo 2010-09-06
  • 打赏
  • 举报
回复
增加你的缓冲区个数,测试了一下,效果还是很不错的。
iBuffersCount = 4;    // uses double-buffering
lihuimin622 2010-09-06
  • 打赏
  • 举报
回复

Unit1.cpp


//---------------------------------------------------------------------------

#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);

}
//---------------------------------------------------------------------------

1,222

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧