如何只记录麦克风输入的声音?

dytsoft 2008-02-27 04:20:31
例如有程序在播放伴奏,然后用麦克风跟着唱,只记录麦克风的声音,生成文件.
...全文
158 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
ouyh12345 2008-02-27
  • 打赏
  • 举报
回复
请参考vckbase、codeproject、codeguru上的例子
ouyh12345 2008-02-27
  • 打赏
  • 举报
回复
应用举例:

CSpeaker _speaker;

//设置采样
_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();

然后在回调函数里处理采集的数据
ouyh12345 2008-02-27
  • 打赏
  • 举报
回复
speaker.cpp

#include <windows.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;
}
ouyh12345 2008-02-27
  • 打赏
  • 举报
回复
speaker.h

#ifndef _SPEAKER_H
#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
ouyh12345 2008-02-27
  • 打赏
  • 举报
回复
waveIn函数族

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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