#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 #include class ProcessFileTaskPrivate { public: void initialize(int sampleRate, int channels, int period) { std::unique_ptr factory = std::make_unique(); echoCanceller = factory->Create(sampleRate, channels, channels); nearendBuffer = std::make_unique(sampleRate, channels, sampleRate, channels, sampleRate, channels); farendBuffer = std::make_unique(sampleRate, channels, sampleRate, channels, sampleRate, channels); linearOutputBuffer = std::make_unique(sampleRate, channels, sampleRate, channels, sampleRate, channels); RKAP_3A_Init(&m_vqe, AEC_TX_TYPE); } std::unique_ptr echoCanceller; std::unique_ptr nearendBuffer; std::unique_ptr farendBuffer; std::unique_ptr 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("/sdcard/speaker_16k.pcm", std::ifstream::binary); m_micIfs = std::make_shared("/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(m_outFilename, std::ofstream::binary); // m_speakerIfs = std::make_shared("/sdcard/speaker_8k.pcm", std::ifstream::binary); // m_micIfs = std::make_shared("/sdcard/micin_8k.pcm", std::ifstream::binary); // m_ofs = std::make_shared("/sdcard/out_8k.pcm", std::ofstream::binary); m_webRtcAecm = std::make_shared(); m_webRtcAecm->start(16000, 1, 10); m_speex = std::make_shared(); 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::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(farendBuffer)); m_speex->echoCapture(reinterpret_cast(nearendBuffer), reinterpret_cast(outBuffer)); } else if (m_dsp == AecMobile) { m_webRtcAecm->echoPlayback(reinterpret_cast(farendBuffer), sizeof(farendBuffer) / 2); m_webRtcAecm->echoCancellation(reinterpret_cast(nearendBuffer), nullptr, reinterpret_cast(outBuffer), sizeof(farendBuffer) / 2); } else if (m_dsp == Aec3) { webrtc::StreamConfig config(16000, 1); // 单声道 m_d->nearendBuffer->CopyFrom(reinterpret_cast(nearendBuffer), config); m_d->farendBuffer->CopyFrom(reinterpret_cast(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(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::system_clock::now() - m_begin); LOG(info) << "process file finished, out: " << m_outFilename << ", elapsed: " << elapsed; std::exit(0); } }