欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

webrtc c++(二) webrtc音频操作麦克风录音与播放,声音控制

程序员文章站 2022-06-12 13:45:23
...

由于新版本的webrtc工程太过于庞大,有一千读个工程,对于理解源码很不方便,所以以后都采用老版本的webrtc,以方便理解,这个版本有一百多个工程,相对于最新的工程要小很多

webrtc源码  下载 链接:

https://pan.baidu.com/s/14ECsWNgQ4ZxrxG0tO22E0w
提取码:ups7

这个版本中webrtc 音频核心为

webrtc::VoiceEngine* ptrVoEngine_;  //核心引擎类,下面的四个类的都是基于引擎创建的
webrtc::VoEBase* ptrVoEBase_;
webrtc::VoEVolumeControl* ptrVoEVolumeControl_;//声音控制类,设置麦克风与声卡的声音等
webrtc::VoEFile* ptrVoEFile_;//音频文件管理,播放文件,保存文件等
webrtc::VoEHardware* ptrVoEHardware_;//设备相关,可以获取设备,打开设备,播放等

 

1.核心类的创建
 

bool videoCap::InitVoiceEnginee()
{
    ptrVoEngine_ = webrtc::VoiceEngine::Create(); //通过全局方法创建引擎

    //通过引擎创建其他类
    ptrVoEBase_ = webrtc::VoEBase::GetInterface(ptrVoEngine_); 

    ptrVoEHardware_ = webrtc::VoEHardware::GetInterface(ptrVoEngine_);
    ptrVoEFile_ = webrtc::VoEFile::GetInterface(ptrVoEngine_);
    ptrVoEVolumeControl_ = webrtc::VoEVolumeControl::GetInterface(ptrVoEngine_);

    int errCode = ptrVoEBase_->Init();
    if (errCode != 0)
    {
        return false;
    }
    
    //注册错误回调
    errCode = ptrVoEBase_->RegisterVoiceEngineObserver(voeObserver_);
    if (errCode != 0)
    {
        return false;
    }
    return true;
}

2 获取音频设备列表(麦克风与音响设备)

void videoCap::setDevice()
{
	int recoder_device_num{ 0 };
	int play_device_num{ 0 };
        //获取所有录制设备信息(麦克风等)
	int errCode = ptrVoEHardware_->GetNumOfRecordingDevices(recoder_device_num);
	if (errCode != 0)
	{
		return;
	}
        
        //获取所以播放设备信息(耳麦音响等)
	errCode = ptrVoEHardware_->GetNumOfPlayoutDevices(play_device_num);
	if (errCode != 0)
	{
		return;
	}

        //获取录制设备详细信息
	for (int i = 0; i < recoder_device_num; ++i)
	{
		char devName[256]{ 0 };
		char guidName[256]{ 0 };
		ptrVoEHardware_->GetRecordingDeviceName(i, devName, guidName);
		ui.m_cbRecoderDev->addItem(devName, i);
	}

        //获取播放设备详细信息
	for (int i = 0; i < recoder_device_num; ++i)
	{
		char devName[256]{ 0 };
		char guidName[256]{ 0 };

		ptrVoEHardware_->GetPlayoutDeviceName(i, devName, guidName);

		ui.m_cbPlayerDev->addItem(devName,i);
	}
        
        //创建channel,以后所有的操作都是基于这个audio_channel_
	audio_channel_ = ptrVoEBase_->CreateChannel();
	if (audio_channel_ < 0)
	{
		qDebug() << "ERROR in VoEBase::CreateChannel";
	}
	errCode = ptrVoEBase_->StartPlayout(audio_channel_);
	if (errCode != 0)
	{
		qDebug() << "ERROR in VoEBase::StartPlayout";
	}

}

3 开始/结束录制

void videoCap::OnOpenPbClicked()
{
	if (ui.m_pbOpen->text() == QString::fromLocal8Bit("打开"))
	{
                //开始录制
		ptrVoEFile_->StartRecordingMicrophone(VIDEO_FILE); 
		ui.m_pbOpen->setText(QString::fromLocal8Bit("关闭"));
	}
	else
	{
                //结束录制
		ptrVoEFile_->StopRecordingMicrophone();
		ui.m_pbOpen->setText(QString::fromLocal8Bit("打开"));
	}
}

4播放/停止

void videoCap::OnPlayPbClicked()
{
        
	if (ui.m_pbPlayer->text() == QString::fromLocal8Bit("播放"))
	{
                //播放
		ptrVoEFile_->StartPlayingFileLocally(audio_channel_, VIDEO_FILE);
		ui.m_pbPlayer->setText(QString::fromLocal8Bit("停止"));
	}
	else
	{
                //停止
		ptrVoEFile_->StopPlayingFileLocally(audio_channel_);
		ui.m_pbPlayer->setText(QString::fromLocal8Bit("播放"));
	}
}

5音量控制

//获取麦克风当前音量
int videoCap::GetMicroVolume()
{
	unsigned int n{ 0 };
	ptrVoEVolumeControl_->GetMicVolume(n);
	ui.m_slider_Speaker->setValue(n);
	return n;
}

//设置麦克风音量
void videoCap::SetMicroVolume(int n)
{
	int errCode = ptrVoEVolumeControl_->SetMicVolume(n);
	if (errCode != 0)
	{
		qDebug() << "set volume failed";
	}
}

//获取音响音量
int videoCap::GetSpeakVolume()
{
	unsigned int n{ 0 };
	ptrVoEVolumeControl_->GetSpeakerVolume(n);
	ui.m_slider_Micro->setValue(n);
	return n;
	
}

//设置音响音量
void videoCap::SetSpeakVolume(int n)
{
	int errCode =	ptrVoEVolumeControl_->SetSpeakerVolume(n);
	if (errCode != 0)
	{
		qDebug() << "set volume failed";
	}
}

6 资源销毁

void videoCap::UnInitVoiceEnginee()
{
	if (ptrVoEFile_->IsPlayingFileLocally(audio_channel_))
	{
		ptrVoEFile_->StopPlayingFileLocally(audio_channel_);
	}
	ptrVoEFile_->StopRecordingMicrophone();
	ptrVoEBase_->StopPlayout(audio_channel_);

	ptrVoEFile_->Release();
	ptrVoEHardware_->Release();

	ptrVoEVolumeControl_->Release();
	ptrVoEBase_->Release();

	webrtc::VoiceEngine::Delete(ptrVoEngine_);
}

7完整代码

//.h文件
#pragma once

#include <QWidget>
#include <QDebug>
#include <mutex>
#include "video_capture/video_capture_factory.h"
#include "base/device.h"
#include "engine/webrtcvideocapturer.h"

#include "webrtc/modules/audio_device/include/audio_device.h"

#include "ui_videoCap.h"

//audio
#include "webrtc/voice_engine/include/voe_hardware.h"
#include "webrtc/voice_engine/include/voe_base.h"
#include "webrtc/voice_engine/voice_engine_defines.h"
#include "webrtc/voice_engine/include/voe_volume_control.h"
#include "webrtc/voice_engine/include/voe_file.h"
#include "webrtc/voice_engine/voice_engine_impl.h"

class VoiceObserver :public webrtc::VoiceEngineObserver
{
public:
	virtual void CallbackOnError(int channel, int errCode) override
	{
		qDebug() << "channel id = " << channel << "errCode = " << errCode;
	}
};

class videoCap:public QWidget
{
public:
	explicit videoCap(QWidget *parent = nullptr);
	~videoCap();

protected:
	virtual void  paintEvent(QPaintEvent *event) override;
private:
	void OnOpenPbClicked();
	void OnPlayPbClicked();

	bool InitVoiceEnginee();

	void UnInitVoiceEnginee();

	void setDevice();

	int GetMicroVolume();
	void SetMicroVolume(int n);

	int GetSpeakVolume();
	void SetSpeakVolume(int n); 
private:
	Ui::Form ui;

	webrtc::VoiceEngine* ptrVoEngine_;
	webrtc::VoEBase* ptrVoEBase_;
	webrtc::VoEVolumeControl* ptrVoEVolumeControl_;
	webrtc::VoEFile* ptrVoEFile_;
	webrtc::VoEHardware* ptrVoEHardware_;
	VoiceObserver voeObserver_;

	int audio_channel_;

};

.cpp文件
#include "videoCap.h"
#include <QPainter>
#include "libyuv/include/libyuv.h"

#define  VIDEO_FILE "1234.pcm"

videoCap::videoCap(QWidget *parent)
	:QWidget(parent)
	,ptrVoEBase_(nullptr)
	,ptrVoEFile_(nullptr)
	,ptrVoEngine_(nullptr)
	,ptrVoEHardware_(nullptr)
	,ptrVoEVolumeControl_(nullptr)
{
	ui.setupUi(this);
	if (!InitVoiceEnginee())
		return;
	setDevice();
	QObject::connect(ui.m_pbOpen,&QPushButton::clicked,this,&videoCap::OnOpenPbClicked);
	QObject::connect(ui.m_pbPlayer,&QPushButton::clicked,this,&videoCap::OnPlayPbClicked);
	ui.m_pbOpen->setText(QString::fromLocal8Bit("打开"));
	ui.m_pbPlayer->setText(QString::fromLocal8Bit("播放"));

	connect(ui.m_slider_Speaker,&QSlider::valueChanged,this,&videoCap::SetSpeakVolume);
	connect(ui.m_slider_Micro, &QSlider::valueChanged, this, &videoCap::SetMicroVolume);
	GetMicroVolume();
	GetSpeakVolume();
}

bool videoCap::InitVoiceEnginee()
{
	ptrVoEngine_ = webrtc::VoiceEngine::Create();
	ptrVoEBase_ = webrtc::VoEBase::GetInterface(ptrVoEngine_);

	ptrVoEHardware_ = webrtc::VoEHardware::GetInterface(ptrVoEngine_);
	ptrVoEFile_ = webrtc::VoEFile::GetInterface(ptrVoEngine_);
	ptrVoEVolumeControl_ = webrtc::VoEVolumeControl::GetInterface(ptrVoEngine_);

	int errCode = ptrVoEBase_->Init();
	if (errCode != 0)
	{
		return false; 
	}

	errCode = ptrVoEBase_->RegisterVoiceEngineObserver(voeObserver_);
	if (errCode != 0)
	{
		return false;
	}
	return true;
}

void videoCap::UnInitVoiceEnginee()
{
	if (ptrVoEFile_->IsPlayingFileLocally(audio_channel_))
	{
		ptrVoEFile_->StopPlayingFileLocally(audio_channel_);
	}
	ptrVoEFile_->StopRecordingMicrophone();
	ptrVoEBase_->StopPlayout(audio_channel_);

	ptrVoEFile_->Release();
	ptrVoEHardware_->Release();

	ptrVoEVolumeControl_->Release();
	ptrVoEBase_->Release();

	webrtc::VoiceEngine::Delete(ptrVoEngine_);
}


videoCap::~videoCap()
{
	UnInitVoiceEnginee();
}

void videoCap::OnOpenPbClicked()
{
	if (ui.m_pbOpen->text() == QString::fromLocal8Bit("打开"))
	{
		ptrVoEFile_->StartRecordingMicrophone(VIDEO_FILE); 
		ui.m_pbOpen->setText(QString::fromLocal8Bit("关闭"));
	}
	else
	{
		ptrVoEFile_->StopRecordingMicrophone();
		ui.m_pbOpen->setText(QString::fromLocal8Bit("打开"));
	}
}

void videoCap::OnPlayPbClicked()
{
	if (ui.m_pbPlayer->text() == QString::fromLocal8Bit("播放"))
	{
		ptrVoEFile_->StartPlayingFileLocally(audio_channel_, VIDEO_FILE);
		ui.m_pbPlayer->setText(QString::fromLocal8Bit("停止"));
	}
	else
	{
		ptrVoEFile_->StopPlayingFileLocally(audio_channel_);
		ui.m_pbPlayer->setText(QString::fromLocal8Bit("播放"));
	}
}

void  videoCap::paintEvent(QPaintEvent *event)
{
	QWidget::paintEvent(event);
}

void videoCap::setDevice()
{
	int recoder_device_num{ 0 };
	int play_device_num{ 0 };
	int errCode = ptrVoEHardware_->GetNumOfRecordingDevices(recoder_device_num);
	if (errCode != 0)
	{
		return;
	}

	errCode = ptrVoEHardware_->GetNumOfPlayoutDevices(play_device_num);
	if (errCode != 0)
	{
		return;
	}

	for (int i = 0; i < recoder_device_num; ++i)
	{
		char devName[256]{ 0 };
		char guidName[256]{ 0 };
		ptrVoEHardware_->GetRecordingDeviceName(i, devName, guidName);
		ui.m_cbRecoderDev->addItem(devName, i);
	}

	for (int i = 0; i < recoder_device_num; ++i)
	{
		char devName[256]{ 0 };
		char guidName[256]{ 0 };

		ptrVoEHardware_->GetPlayoutDeviceName(i, devName, guidName);

		ui.m_cbPlayerDev->addItem(devName,i);
	}

	audio_channel_ = ptrVoEBase_->CreateChannel();
	if (audio_channel_ < 0)
	{
		qDebug() << "ERROR in VoEBase::CreateChannel";
	}
	errCode = ptrVoEBase_->StartPlayout(audio_channel_);
	if (errCode != 0)
	{
		qDebug() << "ERROR in VoEBase::StartPlayout";
	}

}

int videoCap::GetMicroVolume()
{
	unsigned int n{ 0 };
	ptrVoEVolumeControl_->GetMicVolume(n);
	ui.m_slider_Speaker->setValue(n);
	return n;
}

void videoCap::SetMicroVolume(int n)
{
	int errCode = ptrVoEVolumeControl_->SetMicVolume(n);
	if (errCode != 0)
	{
		qDebug() << "set volume failed";
	}
}

int videoCap::GetSpeakVolume()
{
	unsigned int n{ 0 };
	ptrVoEVolumeControl_->GetSpeakerVolume(n);
	ui.m_slider_Micro->setValue(n);
	return n;
	
}

void videoCap::SetSpeakVolume(int n)
{
	int errCode =	ptrVoEVolumeControl_->SetSpeakerVolume(n);
	if (errCode != 0)
	{
		qDebug() << "set volume failed";
	}
}

8编译错误,音频需要依赖的模块

video_capture_module.lib
video_capture_module_internal_impl.lib
common_video.lib
rtc_base.lib
rtc_media.lib
voice_engine.lib
rtc_base_approved.lib
rtc_event_log_proto.lib
rtc_event_log.lib
protobuf_full_do_not_use.lib
protobuf_lite.lib
protoc_lib.lib
system_wrappers.lib
directshow_baseclasses.lib
webrtc_i420.lib
libyuv.lib
Winmm.lib
libjpeg.lib
audio_device.lib
audio_decoder_interface.lib
audio_processing.lib
audio_processing_sse2.lib
audio_coding_module.lib
audio_encoder_interface.lib
audio_decoder_factory_interface.lib
rtp_rtcp.lib
rent_a_codec.lib
isac.lib
audio_conference_mixer.lib
webrtc_utility.lib
webrtc_common.lib
common_audio.lib
openmax_dl.lib
common_audio_sse2.lib
media_file.lib
red.lib
builtin_audio_decoder_factory.lib
isac_common.lib
pcm16b.lib
cng.lib
g711.lib
webrtc_opus.lib
opus.lib
ilbc.lib
g722.lib
neteq.lib
metrics_default.lib
audioproc_debug_proto.lib
paced_sender.lib
msdmo.lib
wmcodecdspuuid.lib
dmoguids.lib

最后三个是directShow的依赖,不是webrtc源码编译出来的,

还有些预处理需要添加

WEBRTC_WIN
QT_NO_KEYWORDS
_DEBUG
NOMINMAX

否则会编译失败

webrtc c++(二) webrtc音频操作麦克风录音与播放,声音控制

参考灿哥哥的博客

https://blog.csdn.net/caoshangpa/article/details/54340229

相关标签: webrtc c++