FaceAccess/Record/EchoRecord.cpp

115 lines
4.7 KiB
C++
Raw Normal View History

2024-09-04 17:57:23 +08:00
#include "BoostLog.h"
2024-09-05 12:24:05 +08:00
#include "SpeexDsp.h"
#include "Utility.h"
#include "WebRtcAecm.h"
2024-09-06 09:45:44 +08:00
#include "api/audio/echo_canceller3_config.h"
#include "api/audio/echo_canceller3_factory.h"
2024-09-04 17:57:23 +08:00
#include "main.h"
2024-09-06 09:45:44 +08:00
#include "modules/audio_processing/aec3/echo_canceller3.h"
2024-09-04 17:57:23 +08:00
#include <memory>
2024-09-06 09:45:44 +08:00
class EchoRecordPrivate {
public:
EchoRecordPrivate() {
std::unique_ptr<webrtc::EchoCanceller3Factory> factory = std::make_unique<webrtc::EchoCanceller3Factory>();
echoCanceller = factory->Create(16000, 1, 1);
// nearendBuffer = std::make_unique<webrtc::AudioBuffer>(16000, 1, 16000, 1, 16000, 1);
// farendBuffer = std::make_unique<webrtc::AudioBuffer>(16000, 1, 16000, 1, 16000, 1);
}
std::unique_ptr<webrtc::EchoControl> echoCanceller;
// std::unique_ptr<webrtc::AudioBuffer> nearendBuffer;
// std::unique_ptr<webrtc::AudioBuffer> farendBuffer;
};
EchoRecordTask::EchoRecordTask() : m_d{new EchoRecordPrivate()} {
}
EchoRecordTask::~EchoRecordTask() {
if (m_d != nullptr) {
delete m_d;
}
}
void EchoRecordTask::setDsp(Dsp dsp) {
if (m_dsp != dsp) {
m_dsp = dsp;
2024-09-04 17:57:23 +08:00
}
}
void EchoRecordTask::setChannels(int channels) {
if (m_channels != channels) {
m_channels = channels;
}
}
2024-09-05 12:24:05 +08:00
// underrun occurred pcm播放饥饿
// 回采信号提前于mic信号时间差<80ms
// ./Record --echo --vqe=false --channels=2
// ./Record --echo --vqe=true --channels=2
// ./Record --echo --vqe=false --channels=1
2024-09-04 17:57:23 +08:00
void EchoRecordTask::run() {
2024-09-06 09:45:44 +08:00
LOG(info) << "dsp use: " << dspToString(m_dsp);
2024-09-05 12:24:05 +08:00
2024-09-04 17:57:23 +08:00
RkAudio::Format format;
format.channels = m_channels;
2024-09-06 09:45:44 +08:00
format.period = 20;
2024-09-05 12:24:05 +08:00
m_speex = std::make_shared<SpeexDsp>();
m_speex->start(format.sampleRate, m_channels, format.period);
m_farendBuffer.resize(m_channels * sizeof(int16_t) * format.sampleRate / 1000 * format.period);
m_nearendBuffer.resize(m_channels * sizeof(int16_t) * format.sampleRate / 1000 * format.period);
m_webRtcAecm = std::make_shared<WebRtcAecm>();
m_webRtcAecm->start(format.sampleRate, format.channels, format.period);
2024-09-04 17:57:23 +08:00
m_output = std::make_shared<RkAudio::Output>();
2024-09-06 09:45:44 +08:00
if (!m_output->open(sizeof(uint16_t), format.sampleRate, 2, format.period, m_dsp == Vqe)) {
2024-09-04 17:57:23 +08:00
LOG(error) << "audio output open failed.";
return;
}
2024-09-05 12:24:05 +08:00
m_outBuffer.resize(m_channels * sizeof(int16_t) * format.sampleRate / 1000 * format.period);
2024-09-04 17:57:23 +08:00
m_input = std::make_shared<RkAudio::Input>();
2024-09-06 09:45:44 +08:00
m_input->setDataCallback([this, format](const RkAudio::Frame &frame) {
2024-09-05 12:24:05 +08:00
memcpy(m_nearendBuffer.data(), frame.data, frame.byteSize);
2024-09-06 09:45:44 +08:00
if (m_dsp == Speex) {
m_speex->echoPlayback(reinterpret_cast<const int16_t *>(m_farendBuffer.data()));
m_speex->echoCapture(reinterpret_cast<const int16_t *>(frame.data), reinterpret_cast<int16_t *>(m_outBuffer.data()));
} else if (m_dsp == AecMobile) {
m_webRtcAecm->echoPlayback(reinterpret_cast<const int16_t *>(m_farendBuffer.data()), m_farendBuffer.size() / 2);
2024-09-05 12:24:05 +08:00
2024-09-06 09:45:44 +08:00
m_webRtcAecm->echoCancellation(reinterpret_cast<int16_t *>(frame.data), reinterpret_cast<int16_t *>(m_nearendBuffer.data()),
reinterpret_cast<int16_t *>(m_outBuffer.data()), frame.frameSize);
} else if (m_dsp == Aec3) {
webrtc::StreamConfig config(format.sampleRate, format.channels); // 单声道
webrtc::AudioBuffer nearendBuffer(format.sampleRate, 1, format.sampleRate, 1, format.sampleRate, 1);
webrtc::AudioBuffer farendBuffer(format.sampleRate, 1, format.sampleRate, 1, format.sampleRate, 1);
webrtc::AudioBuffer linearOutputBuffer(format.sampleRate, 1, format.sampleRate, 1, format.sampleRate, 1);
nearendBuffer.CopyFrom(reinterpret_cast<const int16_t *>(frame.data), config);
2024-09-05 12:24:05 +08:00
2024-09-06 09:45:44 +08:00
farendBuffer.CopyFrom(reinterpret_cast<const int16_t *>(m_farendBuffer.data()), config);
m_d->echoCanceller->AnalyzeRender(&farendBuffer);
m_d->echoCanceller->AnalyzeCapture(&nearendBuffer);
m_d->echoCanceller->ProcessCapture(&nearendBuffer, &linearOutputBuffer, /*level_change=*/false);
linearOutputBuffer.CopyTo(config, reinterpret_cast<int16_t *>(m_outBuffer.data()));
}
2024-09-05 12:24:05 +08:00
if (m_channels == 2) {
m_output->write(frame.data, frame.byteSize);
} else if (m_channels == 1) {
auto filledData = duplicate(m_outBuffer.data(), m_outBuffer.size());
m_output->write(filledData.data(), filledData.size());
}
memcpy(m_farendBuffer.data(), m_outBuffer.data(), m_outBuffer.size());
// m_output->write(reinterpret_cast<const uint8_t *>(m_buffer.data()), m_buffer.size());
});
2024-09-04 17:57:23 +08:00
2024-09-06 09:45:44 +08:00
m_input->open(format, m_dsp == Vqe);
2024-09-04 17:57:23 +08:00
}