#include "BoostLog.h" #include "SpeexDsp.h" #include "Utility.h" #include "WebRtcAecm.h" #include "main.h" #include void EchoRecordTask::setVqeEnabled(bool enabled) { if (m_vqeEnabled != enabled) { m_vqeEnabled = enabled; } } void EchoRecordTask::setChannels(int channels) { if (m_channels != channels) { m_channels = channels; } } // underrun occurred pcm播放饥饿 // 回采信号提前于mic信号,时间差<80ms // ./Record --echo --vqe=false --channels=2 // ./Record --echo --vqe=true --channels=2 // ./Record --echo --vqe=false --channels=1 void EchoRecordTask::run() { RkAudio::Format format; format.channels = m_channels; format.period = 10; m_speex = std::make_shared(); 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(); m_webRtcAecm->start(format.sampleRate, format.channels, format.period); m_output = std::make_shared(); if (!m_output->open(sizeof(uint16_t), format.sampleRate, 2, format.period, m_vqeEnabled)) { LOG(error) << "audio output open failed."; return; } m_outBuffer.resize(m_channels * sizeof(int16_t) * format.sampleRate / 1000 * format.period); m_input = std::make_shared(); m_input->setDataCallback([this](const RkAudio::Frame &frame) { memcpy(m_nearendBuffer.data(), frame.data, frame.byteSize); m_webRtcAecm->echoPlayback(reinterpret_cast(m_farendBuffer.data()), m_farendBuffer.size() / 2); m_webRtcAecm->echoCancellation(reinterpret_cast(frame.data), reinterpret_cast(m_nearendBuffer.data()), reinterpret_cast(m_outBuffer.data()), frame.frameSize); // m_speex->echoPlayback(reinterpret_cast(frame.data)); // m_speex->echoPlayback(reinterpret_cast(m_buffer.data())); // m_speex->echoCapture(reinterpret_cast(frame.data), reinterpret_cast(m_buffer.data())); 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(m_buffer.data()), m_buffer.size()); }); m_input->open(format, m_vqeEnabled); }