114 lines
5.0 KiB
C++
114 lines
5.0 KiB
C++
#include "IoContext.h"
|
|
#include "RKAP_3A.h"
|
|
#include "SpeexDsp.h"
|
|
#include "WebRtcAecm.h"
|
|
#include "api/audio/echo_canceller3_config.h"
|
|
#include "api/audio/echo_canceller3_factory.h"
|
|
#include "main.h"
|
|
#include "modules/audio_processing/aec3/echo_canceller3.h"
|
|
#include <boost/asio/post.hpp>
|
|
#include <sstream>
|
|
|
|
class ProcessFileTaskPrivate {
|
|
public:
|
|
void initialize(int sampleRate, int channels, int period) {
|
|
std::unique_ptr<webrtc::EchoCanceller3Factory> factory = std::make_unique<webrtc::EchoCanceller3Factory>();
|
|
echoCanceller = factory->Create(sampleRate, channels, channels);
|
|
nearendBuffer = std::make_unique<webrtc::AudioBuffer>(sampleRate, channels, sampleRate, channels, sampleRate, channels);
|
|
farendBuffer = std::make_unique<webrtc::AudioBuffer>(sampleRate, channels, sampleRate, channels, sampleRate, channels);
|
|
linearOutputBuffer = std::make_unique<webrtc::AudioBuffer>(sampleRate, channels, sampleRate, channels, sampleRate, channels);
|
|
|
|
RKAP_3A_Init(&m_vqe, AEC_TX_TYPE);
|
|
}
|
|
|
|
std::unique_ptr<webrtc::EchoControl> echoCanceller;
|
|
std::unique_ptr<webrtc::AudioBuffer> nearendBuffer;
|
|
std::unique_ptr<webrtc::AudioBuffer> farendBuffer;
|
|
std::unique_ptr<webrtc::AudioBuffer> linearOutputBuffer;
|
|
|
|
RKAP_AEC_State m_vqe;
|
|
};
|
|
|
|
ProcessFileTask::ProcessFileTask() : m_d{new ProcessFileTaskPrivate()} {
|
|
}
|
|
|
|
ProcessFileTask::~ProcessFileTask() {
|
|
if (m_d != nullptr) {
|
|
delete m_d;
|
|
}
|
|
}
|
|
|
|
void ProcessFileTask::setDsp(Dsp dsp) {
|
|
if (m_dsp != dsp) {
|
|
m_dsp = dsp;
|
|
}
|
|
}
|
|
|
|
// ./Record --file --dsp=aecm
|
|
void ProcessFileTask::run() {
|
|
m_speakerIfs = std::make_shared<std::ifstream>("/sdcard/speaker_16k.pcm", std::ifstream::binary);
|
|
m_micIfs = std::make_shared<std::ifstream>("/sdcard/micin_16k.pcm", std::ifstream::binary);
|
|
|
|
std::ostringstream oss;
|
|
oss << DumpPath << "/out_" << dspToString(m_dsp) << "_16k.pcm";
|
|
m_outFilename = oss.str();
|
|
m_ofs = std::make_shared<std::ofstream>(m_outFilename, std::ofstream::binary);
|
|
|
|
// m_speakerIfs = std::make_shared<std::ifstream>("/sdcard/speaker_8k.pcm", std::ifstream::binary);
|
|
// m_micIfs = std::make_shared<std::ifstream>("/sdcard/micin_8k.pcm", std::ifstream::binary);
|
|
// m_ofs = std::make_shared<std::ofstream>("/sdcard/out_8k.pcm", std::ofstream::binary);
|
|
|
|
m_webRtcAecm = std::make_shared<WebRtcAecm>();
|
|
m_webRtcAecm->start(16000, 1, 10);
|
|
|
|
m_speex = std::make_shared<SpeexDsp>();
|
|
m_speex->start(16000, 1, 10);
|
|
|
|
m_d->initialize(16000, 1, 10);
|
|
m_begin = std::chrono::system_clock::now();
|
|
process();
|
|
}
|
|
|
|
void ProcessFileTask::process() {
|
|
using namespace Amass;
|
|
auto ioConext = Singleton<IoContext>::instance();
|
|
if (m_speakerIfs && m_micIfs && *m_speakerIfs && *m_micIfs) {
|
|
char farendBuffer[sizeof(int16_t) * 16000 / 1000 * 10] = {0};
|
|
char nearendBuffer[sizeof(int16_t) * 16000 / 1000 * 10] = {0};
|
|
char outBuffer[sizeof(int16_t) * 16000 / 1000 * 10] = {0};
|
|
// char farendBuffer[sizeof(int16_t) * 8000 / 1000 * 10] = {0};
|
|
// char nearendBuffer[sizeof(int16_t) * 8000 / 1000 * 10] = {0};
|
|
// char outBuffer[sizeof(int16_t) * 8000 / 1000 * 10] = {0};
|
|
|
|
m_speakerIfs->read(farendBuffer, sizeof(farendBuffer));
|
|
m_micIfs->read(nearendBuffer, sizeof(nearendBuffer));
|
|
if (m_dsp == Speex) {
|
|
m_speex->echoPlayback(reinterpret_cast<const int16_t *>(farendBuffer));
|
|
m_speex->echoCapture(reinterpret_cast<const int16_t *>(nearendBuffer), reinterpret_cast<int16_t *>(outBuffer));
|
|
} else if (m_dsp == AecMobile) {
|
|
m_webRtcAecm->echoPlayback(reinterpret_cast<const int16_t *>(farendBuffer), sizeof(farendBuffer) / 2);
|
|
m_webRtcAecm->echoCancellation(reinterpret_cast<int16_t *>(nearendBuffer), nullptr, reinterpret_cast<int16_t *>(outBuffer),
|
|
sizeof(farendBuffer) / 2);
|
|
} else if (m_dsp == Aec3) {
|
|
webrtc::StreamConfig config(16000, 1); // 单声道
|
|
m_d->nearendBuffer->CopyFrom(reinterpret_cast<const int16_t *>(nearendBuffer), config);
|
|
|
|
m_d->farendBuffer->CopyFrom(reinterpret_cast<const int16_t *>(farendBuffer), config);
|
|
|
|
m_d->echoCanceller->AnalyzeRender(m_d->farendBuffer.get());
|
|
m_d->echoCanceller->AnalyzeCapture(m_d->nearendBuffer.get());
|
|
m_d->echoCanceller->ProcessCapture(m_d->nearendBuffer.get(), false);
|
|
// m_d->echoCanceller->ProcessCapture(&nearendBuffer, &linearOutputBuffer, /*level_change=*/false);
|
|
|
|
m_d->nearendBuffer->CopyTo(config, reinterpret_cast<int16_t *>(outBuffer));
|
|
} else if (m_dsp == Vqe) {
|
|
}
|
|
|
|
m_ofs->write(outBuffer, sizeof(outBuffer));
|
|
boost::asio::post(*ioConext->ioContext(), [this]() { process(); });
|
|
} else {
|
|
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - m_begin);
|
|
LOG(info) << "process file finished, out: " << m_outFilename << ", elapsed: " << elapsed;
|
|
std::exit(0);
|
|
}
|
|
} |