例如有程序在播放伴奏,然后用麦克风跟着唱,只记录麦克风的声音,生成文件.
解决方案 »
- 7-zip源代码中压缩文件和解压缩的函数分别是什么啊??
- 问个小问题
- 【HELP】为什么我的 VC 在一打开我的一个大工程就死机了?
- 怎样改变对话框的背景色,怎样创建圆形的按钮:??
- QQ源代码!(本机测试正常)为何不能够和远程计算机通讯
- _beginthreadex()是工作线程,一次执行完后线程就结束了,用它如何能监视串口呀?神呀,救救我吧,我快不行了!
- MDI窗口客户区如何加载bmp图像,并且大小随着变化?急!!!!
- asp作东西我在链接数据库时,插入数据集时,高级选项中总是有[ODBC Microsoft access 参数不足,期待值是2],这是为什么,请高手指点!!!
- QQ的消息记录文件是怎么实现的呀?数据库?
- 问一下这个问题!
- 菜鸟请教CListCtr的EnbaleWindow()问题
- CFtpFileFind类FindFile问题
#define _SPEAKER_H#include "MMSystem.h"typedef enum _enum_speaker_status
{
SPEAKER_INVALID, ///< 无效的状态
SPEAKER_RECORDING ///< 正在录音
}SPEAK_STATUS;#define SPEAK_SUCCEED 0 ///< 正确
#define SPEAK_ERR_FORMAT 1 ///< 没设置采样格式
#define SPEAK_ERR_CALLBACK 2 ///< 没设置回调函数#define HDR_COUNT 2 ///< 录音的缓冲数量typedef void (__stdcall *PFN_SpeakerBufferCallBack)(BOOL result, char *buffer, int buf_len);class CSpeaker
{
public:
//调用接口
CSpeaker();
~CSpeaker(); /**
* \brief 设置录音格式
* \param sampels_per_sec: [in] 速率
* \param bit_per_sample: [in] 采样
* \param channels: [in] 声道数
*/
void SetSpeakerFormat(DWORD sampels_per_sec, WORD bit_per_sample, WORD channels); /**
* \brief 设置回调函数,录音后,以此回调函数返回音频数据
* \param get_buffer_callback: [in] 回调函数
*/
void SetSpeakerBufferCallBack(PFN_SpeakerBufferCallBack get_buffer_callback); /**
* \brief 开始录音
* \param buffer_size: [in] 设置缓存区大小
* \param err_msg: [out] 如果有错误,则返回错误信息
* \param err_len: [in] 错误信息的长度
* \retval: 0为正确,否则为错误号
* 注意: 如果返回值为SPEAK_ERR_FORMAT或SPEAK_ERR_CALLBACK,则应先调用SetFormat或SetGetWaveInBufferCallBack
* 其它的错误表明没有录音设备或设备不可用,或内存不够
*/
int StartSpeaker(int buffer_size, char *err_msg, int err_len); /**
* \brief 停止录音
*/
void StopSpeaker();public:
/**
* \brief 录音函数,此函数被回调函数VoiceWaveInProc,外部程序不应该调用它
*/
BOOL VoiceWaveInFun();private:
void PrepareBuffer();
void Clean();private:
BOOL _is_format_setted; int _buffer_size;
int _hdr_index; SPEAK_STATUS _speaker_status;
HWAVEIN _wave_in_handle;
WAVEFORMATEX _wave_in_format;
PWAVEHDR _wave_in_hdr[HDR_COUNT];
char *_wave_in_buffer[HDR_COUNT]; PFN_SpeakerBufferCallBack _speaker_buffer_callback_fun;
HANDLE _stop_speak_event;
};#endif //_SPEAKER_H
#include "Speaker.h"#define WAVE_ERROR_MSG(result,msg,len) \
if (msg != NULL)\
{\
memset(msg, 0, len);\
waveInGetErrorText(result, msg, len);\
}BOOL CALLBACK VoiceWaveInProc(
HWAVEIN hwi,
UINT uMsg,
DWORD dwInstance,
DWORD dwParam1,
DWORD dwParam2
)
{
BOOL ret = TRUE;
if (uMsg == WIM_DATA)
{
CSpeaker *pthis = (CSpeaker *)dwInstance;
ret = pthis->VoiceWaveInFun();
} return ret;
}CSpeaker::CSpeaker() :
_speaker_buffer_callback_fun(NULL),
_is_format_setted(FALSE),
_buffer_size(0),
_hdr_index(0),
_speaker_status(SPEAKER_INVALID),
_wave_in_handle(NULL),
//_wave_in_hdr(NULL),
//_wave_in_buffer(NULL),
_stop_speak_event(NULL)
{
for (int i = 0; i < HDR_COUNT; i++)
{
_wave_in_hdr[i] = NULL;
_wave_in_buffer[i] = NULL;
}
memset(&_wave_in_format, 0, sizeof(WAVEFORMATEX));
}CSpeaker::~CSpeaker()
{
StopSpeaker();
if (_stop_speak_event != NULL)
{
CloseHandle(_stop_speak_event);
_stop_speak_event = NULL;
}
}void CSpeaker::SetSpeakerFormat(DWORD sampels_per_sec, WORD bit_per_sample, WORD channels)
{
_wave_in_format.cbSize = 0;
_wave_in_format.wFormatTag = WAVE_FORMAT_PCM;
_wave_in_format.nChannels = channels;
_wave_in_format.nSamplesPerSec = sampels_per_sec;
_wave_in_format.wBitsPerSample = bit_per_sample;
_wave_in_format.nBlockAlign = channels * bit_per_sample / 8;
_wave_in_format.nAvgBytesPerSec = sampels_per_sec * channels * bit_per_sample / 8; _is_format_setted = TRUE;
}void CSpeaker::SetSpeakerBufferCallBack(PFN_SpeakerBufferCallBack get_buffer_callback)
{
_speaker_buffer_callback_fun = get_buffer_callback;
}int CSpeaker::StartSpeaker(int buffer_size, char *err_msg, int err_len)
{
MMRESULT mm_res = 0;
int ret = SPEAK_SUCCEED;
_buffer_size = buffer_size;
do
{
if (!_is_format_setted)
{
if (err_msg != NULL)
strncpy(err_msg, "请先设置录音格式", err_len);
ret = SPEAK_ERR_FORMAT;
break;
} if (_speaker_buffer_callback_fun == NULL)
{
if (err_msg != NULL)
strncpy(err_msg, "请先设置回调函数", err_len);
ret = SPEAK_ERR_CALLBACK;
break;
} if (0 != (mm_res = waveInOpen(&_wave_in_handle, (UINT)WAVE_MAPPER ,&_wave_in_format, (DWORD)VoiceWaveInProc, (DWORD)this, CALLBACK_FUNCTION)))
{
ret = mm_res;
break;
} PrepareBuffer(); _hdr_index = 0;
waveInPrepareHeader(_wave_in_handle, _wave_in_hdr[_hdr_index], sizeof(WAVEHDR));
waveInAddBuffer(_wave_in_handle, _wave_in_hdr[_hdr_index], sizeof (WAVEHDR)); if (_stop_speak_event == NULL)
_stop_speak_event = CreateEvent(NULL, FALSE, FALSE, NULL); if (0 != (mm_res = waveInStart(_wave_in_handle)))
{
ret = mm_res;
break;
} _speaker_status = SPEAKER_RECORDING;
return ret;
}while (0);
WAVE_ERROR_MSG(mm_res, err_msg, err_len)
Clean();
return ret;
}void CSpeaker::StopSpeaker()
{
if (_speaker_status == SPEAKER_RECORDING)
{
_speaker_status = SPEAKER_INVALID;
if (_stop_speak_event)
WaitForSingleObject(_stop_speak_event, 1000);
} Clean();
}void CSpeaker::PrepareBuffer()
{
for (int i = 0; i < HDR_COUNT; i++)
{
if (_wave_in_buffer[i] != NULL)
delete []_wave_in_buffer[i]; _wave_in_buffer[i] = new char[_buffer_size];
memset(_wave_in_buffer[i], 0, _buffer_size); if (_wave_in_hdr[i] != NULL)
delete _wave_in_hdr[i]; _wave_in_hdr[i] = new WAVEHDR;
memset(_wave_in_hdr[i], 0, sizeof(WAVEHDR)); _wave_in_hdr[i]->lpData = (LPTSTR)_wave_in_buffer[i];
_wave_in_hdr[i]->dwBufferLength = _buffer_size;
_wave_in_hdr[i]->dwBytesRecorded = 0;
_wave_in_hdr[i]->dwUser = 0;
_wave_in_hdr[i]->dwFlags = 0;
_wave_in_hdr[i]->dwLoops = 1;
_wave_in_hdr[i]->lpNext = NULL;
_wave_in_hdr[i]->reserved = 0;
}
}BOOL CSpeaker::VoiceWaveInFun()
{
if (_speaker_status == SPEAKER_INVALID)
{
if (_stop_speak_event != NULL)
SetEvent(_stop_speak_event);
return FALSE;
} _speaker_buffer_callback_fun(TRUE, _wave_in_buffer[_hdr_index], _buffer_size); if (_speaker_status == SPEAKER_INVALID)
{
if (_stop_speak_event != NULL)
SetEvent(_stop_speak_event);
return FALSE;
} MMRESULT mm_res = 0; do
{
if (0 != (mm_res = waveInUnprepareHeader(_wave_in_handle, _wave_in_hdr[_hdr_index], sizeof(WAVEHDR))))
break; _hdr_index++;
_hdr_index %= HDR_COUNT; if (0 != (mm_res = waveInPrepareHeader(_wave_in_handle, _wave_in_hdr[_hdr_index], sizeof(WAVEHDR))))
break; if (0 != (mm_res = waveInAddBuffer(_wave_in_handle, _wave_in_hdr[_hdr_index], sizeof(WAVEHDR))))
break; return TRUE;
}while (0);
char msg[100];
WAVE_ERROR_MSG(mm_res, msg, 100) _speaker_buffer_callback_fun(FALSE, msg, 100); Clean(); _speaker_status = SPEAKER_INVALID; return FALSE;
}void CSpeaker::Clean()
{
if (_wave_in_handle != NULL)
{
waveInReset(_wave_in_handle);
waveInClose(_wave_in_handle);
_wave_in_handle = NULL;
} for (int i = 0; i < HDR_COUNT; i++)
{
if (_wave_in_buffer[i] != NULL)
{
delete []_wave_in_buffer[i];
_wave_in_buffer[i] = NULL;
} if (_wave_in_hdr[i] != NULL)
{
delete _wave_in_hdr[i];
_wave_in_hdr[i] = NULL;
}
}
_hdr_index = 0;
_is_format_setted = FALSE;
_speaker_buffer_callback_fun = NULL;
}
_speaker.SetSpeakerFormat(BIT_RATE_16000, 16, 1);//设置录音回调函数
_speaker.SetSpeakerBufferCallBack((PFN_SpeakerBufferCallBack)GetSpeakerDataFun);//开始录音
char err_msg[100];
memset(err_msg, 0, sizeof(err_msg));
if (0 != _speaker.StartSpeaker(1024, err_msg, 100))
{
....
}//停止
_speaker.StopSpeaker();然后在回调函数里处理采集的数据