⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recwav.cpp

📁 wince平台下的一个录音机
💻 CPP
字号:
#include "stdafx.h"
#include "recwav.h"
#include "util.h"
#include <stdlib.h>

static HINSTANCE hInst;		// Instance handle
static HWND hwndMain;		//Main window handle
static HDC whdc;
static HMODULE hMod;
static HPEN hpenB,hpenG,hpenOld;
static HWAVEIN hwi;
static WAVEHDR *pwhi,whis[MAX_INQUEU];
static char waveBufferRecord[MAX_INQUEU][REC_BUFSIZE];
static DWORD currWavHdr=0,nextWavHdr;
static BOOL b_playing;
static int mic_status = MIC_OFF;
FILE *fp_wav = NULL;

// wave buffer
char wave_buf[MAX_WAVE_BUF_LEN];
int wave_buf_pos = 0;
int max_wave_buf_len = MAX_WAVE_BUF_LEN;

int waveInit(HWND hWnd,WORD FormatTag,WORD Channel,DWORD Samples,WORD Bits, char *file_wave)
{
	WAVEFORMATEX wfx;
	long k;

	if( micIsOn() )
		return 0;

	wave_buf_pos = 0;
	memset(wave_buf, 0, sizeof(char) * max_wave_buf_len);

	fp_wav = fopen(file_wave, "wb");
	if( !fp_wav )
	{
		AfxMessageBox(L"Error: Cannot write to wave file!");
		return -1;
	}

	setMicOn();

	memset(&wfx,0,sizeof(WAVEFORMATEX));
	wfx.wFormatTag=WAVE_FORMAT_PCM;
	wfx.nChannels=Channel;
	wfx.wBitsPerSample=Bits;
	wfx.nSamplesPerSec=Samples;
	wfx.nBlockAlign=Bits*Channel/8;
	wfx.nAvgBytesPerSec=Samples*Bits*Channel/8;
	wfx.cbSize=0;
	waveInOpen(&hwi,0,&wfx,(DWORD)hWnd,0,CALLBACK_WINDOW|WAVE_MAPPED);
	for(k=0;k<MAX_INQUEU;k++)
	{
		pwhi=&whis[k];
		pwhi->dwFlags=0;
		pwhi->dwLoops=0;
		pwhi->dwBytesRecorded=0;
		pwhi->dwBufferLength=REC_BUFSIZE;
		pwhi->lpData=waveBufferRecord[k];
	}
	for(k=0;k<MAX_INQUEU-1;k++)
	{
		pwhi=&whis[k];
		waveInPrepareHeader(hwi,pwhi,sizeof(WAVEHDR));
		waveInAddBuffer(hwi,pwhi,sizeof(WAVEHDR));
	}
	currWavHdr=0;
	pwhi=&whis[currWavHdr];
	b_playing=TRUE;
	waveInStart(hwi);

	return 0;
}

int waveProcBuf(WAVEHDR *whdr)
{
	// write to wave file
	//fwrite(whdr->lpData, 1, whdr->dwBytesRecorded, fp_wav);
	if( wave_buf_pos + whdr->dwBytesRecorded < max_wave_buf_len )
	{
		memcpy(wave_buf + wave_buf_pos, whdr->lpData, whdr->dwBytesRecorded);
		wave_buf_pos += whdr->dwBytesRecorded;
	}

	// prepare for next buf
	waveInUnprepareHeader(hwi,LPWAVEHDR(pwhi),sizeof(WAVEHDR));		
	nextWavHdr=(currWavHdr-1+MAX_INQUEU)%MAX_INQUEU;
	currWavHdr=(currWavHdr+1)%MAX_INQUEU;
	if(b_playing)
	{
		pwhi=&whis[nextWavHdr];
		pwhi->dwFlags=0;
		pwhi->dwLoops=0;
		waveInPrepareHeader(hwi,pwhi,sizeof(WAVEHDR));
		waveInAddBuffer(hwi,pwhi,sizeof(WAVEHDR));
	}

	return 0;
}

int waveCloseBuf(void)
{
	int i;
	int ret;

	if( micIsOff() )
		return 0;

	b_playing=FALSE;
	waveInReset(hwi);
	for(i=0;i<MAX_INQUEU;i++)
	{
		waveInUnprepareHeader(hwi,pwhi,sizeof(WAVEHDR));
	}
	waveInClose(hwi);

	if( wave_buf_pos != fwrite(wave_buf, 1, wave_buf_pos, fp_wav) )
	{
		ret = -1;
	}else{
		ret = 0;
	}
	fclose(fp_wav);
	wave_buf_pos = 0;

	setMicOff();
	return ret;
}

bool micIsOff(void)
{
	return mic_status == MIC_OFF ? true : false;
}

bool micIsOn(void)
{
	return mic_status == MIC_ON ? true : false;
}

void setMicOn(void)
{
	mic_status = MIC_ON;
}

void setMicOff(void)
{
	mic_status = MIC_OFF;
}

int displayResult(const char *file_result, CListBox *m_listbox)
{
	char line[MAX_LINE_LEN];
	TCHAR wc_buf[MAX_LINE_LEN];

	if( !file_result) 
		return -1;

	FILE *fp = fopen(file_result, "rt");
	if( !fp )
	{
		return -1;
	}

	while(fgets(line, MAX_LINE_LEN, fp))
	{
		char2unicode(line, wc_buf, MAX_LINE_LEN);
		m_listbox->InsertString(0, wc_buf);		
	}
	fclose(fp);

	return 0;
}

// convert char to unicode
int char2unicode(const char *result, TCHAR *wc_result, int max_wc_len)
{	
	memset(wc_result, 0, max_wc_len * sizeof(TCHAR));
		//计算从Ansi转换到Unicode后需要的字节数
		int widecharlen=MultiByteToWideChar(
                CP_ACP,
                MB_COMPOSITE,
                (char*)result, //要转换的Ansi字符串
                -1, //自动计算长度
                0,
                0
        );

		//从Ansi转换到Unicode字符
		MultiByteToWideChar(
			CP_ACP,
			MB_COMPOSITE,
			(char*)result,
			-1,
			wc_result, //转换到wc_buf
			max_wc_len
			//widecharlen //最多转换widecharlen个Unicode字符
        );

		// if input string too long, return -1, otherwise return 0
		return ( widecharlen > max_wc_len ) ? -1 : 0;
}

// unicode to convert char
int unicode2char(const TCHAR *wc_result, int wc_len, char *result, int max_len)
{
	memset(result, 0, sizeof(char)*max_len);

		//计算从Unicode转换到Ansi后需要的字节数
		int charlen = WideCharToMultiByte(
			CP_ACP, //根据ANSI code page转换
			WC_COMPOSITECHECK | WC_DEFAULTCHAR, //转换出错用缺省字符代替
			wc_result, //要转换的字符串地址
            wc_len, //要转换的个数
            0, //转换后字符串放置的地址
            0, //最多转换字符的个数,为0表示返回转换Unicode后需要多少个字节
            0, //缺省的字符:"\0"
            0 //缺省的设置
         );

		WideCharToMultiByte( //转换Unicode到Ansi
			CP_ACP,
			WC_COMPOSITECHECK | WC_DEFAULTCHAR,
			wc_result,
			wc_len,
			(char *)result, //转换到缓冲区中
			max_len, //最多128个字节
			0,
			0);

		// if input string too long, return -1, otherwise return 0
		return ( charlen > max_len ) ? -1 : 0;
}

// compute the percentage of energe
int compEnerge(const char *buf, int len)
{
	int i;
	int energe = 0;
	int step = 10;

	for(i = 0; i < len; i += step)
	{
		int a = (unsigned char)buf[i];
		if( a < 128 )
			energe += 128 - a;
		else
			energe += a - 128;
	}

	energe = (energe * 100 * 2 * step)/(128 * len);
	
	return energe;
}

// detect a wave is sil or not
int isSilWav(const char *buf, int len)
{
	return is_wav_sil(1, (const unsigned char*)buf, len);	
}

/* filter the silence from wave file */
int filter_wav_sil(const char *file)
{
#define BEGIN		0
#define MIDDLE		1
#define END			2

	unsigned char	buf[2000];
	unsigned char	*tmp_buf;
	int			len;
	FILE		*fp;
	FILE		*fp_tmp;
	int			max_len;
	char		file_tmp[256];
	_t_wavhead	wavhead;
	int			write_len;
	int			total_len;
	int			tmp_len;
	int			write;
	int			status;
	int			sil_cnt ;

//#if 1
#ifdef _DEBUG
	char		file_tmp2[256];

	sprintf(file_tmp2, "%s.orig.wav", file);
	
	//copyfile(file, file_tmp2);
	//dbgMsg("(file: %s) (orig len: %4.3f sec) (non-sil len: %4.3f sec)", 
	//	file, (float)total_len/8000, (float)write_len/8000);
#endif


	sprintf(file_tmp, "%s.tmp", file);
    fp = fopen(file, "rb");
	fp_tmp = fopen(file_tmp, "wb");
	max_len = 1600;
	write_len = 0;

    if( !fp )
    {
		//errMsg("cannot open file %s", file);
		return -1;
	}

	/* skip the head of wave file */
	fseek(fp, 50, SEEK_SET);

	/* write output wave head */
	memset(&wavhead, 0, sizeof(wavhead));
    memcpy(wavhead.riff,"RIFF",4);	// RIFF format identifier
    wavhead.size_8=36;	// 36 - jsut size of header
    memcpy(wavhead.wave,"WAVE",4);	// WAVE format
    memcpy(wavhead.fmt,"fmt ",4);	// fmt
    wavhead.pcm=16;			// code for pcm
    wavhead.unknown=1;				
    wavhead.channel=1;			// number of channels
    wavhead.rate=REC_WAVE_FREQ;			// sample rate
    wavhead.byteps=REC_WAVE_FREQ*REC_WAVE_BIT/8;		// Bytes by second
    wavhead.bytepe=1;			// Bytes per sample	
    wavhead.quent=8;			// Bits per sample
    memcpy(wavhead.data,"data",4);	// constant
    wavhead.datasize=write_len;	// no of bytes of wave data
    
	//fwrite(&wavhead, sizeof(wavhead), 1, fp_tmp);
    	
	tmp_buf = (unsigned char*)malloc(10000);
	if( !tmp_buf ) {
		//errMsg("cannot alloc %d Bytes", 10000);
		return -1;
	}

	write_len	= 0;
	total_len	= 0;
	tmp_len		= 0;
	write		= 0;
	sil_cnt		= 0;
	status		= BEGIN;
	while( len = fread(buf, 1, max_len, fp) )
	{
		switch (status)
		{
		case BEGIN:
			if ( !is_wav_sil(1,buf,len) )
			//if( 1 )
			{
				write = 1;
				status = MIDDLE;
				sil_cnt = 0;
			}else{
				memcpy(tmp_buf, buf, len);
				tmp_len = len;
			}
			break;
		case MIDDLE:
			if( is_wav_sil(1, buf, len) )
			{
				sil_cnt ++;
				write = 0;
				if( sil_cnt < 2 )
				{		
					write = 1;
				}else if( sil_cnt < 5 ){
					memcpy(tmp_buf , buf, len);
					tmp_len = len;
					write	= 0;
				}else{
					/* too many silence, treat it as end of wave file */
					write = 0; /* wirte a silence to end of file */					
					// if( tmp_len > 1600 ) tmp_len = 1600;
					//len = 0;
					//status = END;
				}
			}else{
				sil_cnt = 0;
				write	= 1;				
			}		
			break;

		default:
			break;
		}

#ifdef _DEBUG
		//dbgMsg("(status:%d) (tmp_len:%d) (len:%d) (write:%d)",
		//	status, tmp_len, len, write);
#endif
		if( write )
		{
			fwrite(tmp_buf, 1, tmp_len, fp_tmp);
			write_len += tmp_len;

			fwrite(buf, 1, len, fp_tmp);
			write_len += len;

			tmp_len = 0;
			len		= 0;
			write	= 0;
		}

		total_len += len;		

		if( END == status ) break;
	}

	if( 0 == write_len )
	{
		//if the file is all silence, we still need to 
		//write sth to output file to avoid mfcc fault
		int sil_len= 800;
		memset(buf, 0x80, sil_len);
		fwrite(buf, 1,sil_len, fp_tmp);
		write_len = sil_len;
	}
	fclose(fp);
	free(tmp_buf);
	fclose(fp_tmp);
	
	wavhead.datasize = write_len;	// no of bytes of wave data
//#if 1	
#ifdef _DEBUG
	// backup original wave file
	rename(file, file_tmp2);
#endif

	// write the new wave to file
    fp = fopen(file, "wb");
	if( !fp )
		return -1;
	fp_tmp = fopen(file_tmp, "rb");
	if( !fp_tmp )
	{
		fclose(fp);
		return -1;
	}
	fwrite(&wavhead, 1, sizeof(_t_wavhead), fp);
	while( int n = fread(buf, 1, 1024, fp_tmp) )
	{
		fwrite(buf, 1, n, fp);
	}
	fclose(fp_tmp);
	fclose(fp);

	remove(file_tmp);
//#if 0
//#ifndef _DEBUG
	//remove(file);
//#endif

	return 0;
}

// is a piece of wave silence or not
int is_wav_sil(int multiplier, 
			  const unsigned char* data, int len)
{
    int winsize = 200;
    int sample;
    int s = 0;
    int nMinCZR = winsize;
    int nMaxCZR = 0;
    double energy = 0.0;
    int nCZR = 0;
    float numerator;
    int i;
    if (multiplier < 1) 
    	multiplier = 1;
	int bIsSil = 1;

#ifdef WAVE_DETECT_ZERO_STATUS
	int zero_cnt = 0;
	int zero_status = 0;
	int last_zero_status = 0;
#endif

    for (i = 0; i < len - 1; i++) {
#ifdef WAVE_DETECT_ZERO_STATUS
		if( data[i] > 127 )
		{
			zero_status = 0;
		}else{
			zero_status = 1;
		}
		if( zero_status != last_zero_status )
			zero_cnt ++;

		last_zero_status = zero_status;
#endif

		if (s == winsize) {
			nMinCZR = (nMinCZR > nCZR) ? nCZR : nMinCZR;
			nMaxCZR = (nMaxCZR < nCZR) ? nCZR : nMaxCZR;
			nCZR = 0;
			s = 0;
		}
		if ( ( (data[i] ^ data[i+1]) & 0x80 ) != 0)
			nCZR++;
		sample = ((int)data[i] - 128) * multiplier;
		sample = (sample > 127) ? 127 : (sample < -128 ? -128 : sample);
		energy += sample * sample;
		s++;
    }

#ifdef WAVE_DETECT_ZERO_STATUS
	// 如果过零率太小,认为是silence
	if( MIN_ZERO_CNT > zero_cnt )
			return bIsSil;
#endif

    sample = ((int)data[i] - 128) * multiplier;
    sample = (sample > 127) ? 127 : (sample < -128 ? -128 : sample);
    energy += sample * sample;

    numerator = (float)len;
    energy /= numerator;		//	To be average for short block
    numerator = (float) winsize;
    {
	float fltInitCZR  = (float) nMaxCZR / numerator;
	float fltFinalCZR = (float) nMinCZR / numerator;
	if (energy >= 25)
	    bIsSil = 0;
	else if (energy > 12.5 
		 && (fltInitCZR > 0.30f || fltFinalCZR < 0.125f))
	    bIsSil = 0;
	else if (energy > 7.5 && ( fltInitCZR > 0.35f)) 
	    bIsSil = 0; 

	return bIsSil;
    }
}

int remove(const char *file)
{
	TCHAR pFile[MAX_FILE_LEN];

	char2unicode(file, pFile, MAX_FILE_LEN);
	
	CFile::Remove( pFile );

	return 0;
}
	
int rename(const char *old_file, const char *new_file)
{
	TCHAR pOldName[MAX_FILE_LEN];
	TCHAR pNewName[MAX_FILE_LEN];

	char2unicode(old_file, pOldName, MAX_FILE_LEN);
	char2unicode(new_file, pNewName, MAX_FILE_LEN);

	CFile::Rename( pOldName, pNewName );

	return 0;
}	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -