FaceAccess/Record/RkAudio.cpp
2024-06-18 14:27:48 +08:00

188 lines
5.3 KiB
C++

#include "RkAudio.h"
#include "BoostLog.h"
#include <cstring>
#include <rkmedia/rkmedia_api.h>
namespace RkAudio {
static SAMPLE_FORMAT_E rkAiFormat(Format::SampleType sampleType) {
SAMPLE_FORMAT_E ret = RK_SAMPLE_FMT_NONE;
switch (sampleType) {
case Format::SampleType::Unknown:
ret = RK_SAMPLE_FMT_NONE;
break;
case Format::SampleType::SignedInt16:
ret = RK_SAMPLE_FMT_S16;
break;
case Format::SampleType::SignedInt:
ret = RK_SAMPLE_FMT_S32;
break;
case Format::SampleType::Float:
ret = RK_SAMPLE_FMT_FLT;
break;
default:
LOG(error) << "unkonwn sample type: " << static_cast<int>(sampleType);
ret = RK_SAMPLE_FMT_NONE;
break;
}
return ret;
}
Input::Input() {
}
Input::~Input() {
if (m_channel >= 0) {
stop();
}
}
bool Input::open(const Format &format) {
bool ret = false;
// RK_MPI_SYS_DumpChn(RK_ID_AI);
m_channel = 0;
AI_CHN_ATTR_S parameter = {0};
parameter.pcAudioNode = "default";
parameter.enAiLayout = AI_LAYOUT_MIC_REF; // remove ref channel, and output mic mono
parameter.enSampleFormat = rkAiFormat(format.sampleType);
parameter.u32Channels = format.channels;
parameter.u32SampleRate = format.sampleRate;
parameter.u32NbSamples = format.sampleRate / 1000 * format.period;
int status = RK_MPI_AI_SetChnAttr(m_channel, &parameter);
if (status) {
LOG(error) << "RK_MPI_AI_SetChnAttr() failed, status: " << status;
return ret;
}
status = RK_MPI_AI_EnableChn(m_channel);
if (status) {
LOG(error) << "RK_MPI_AI_EnableChn() failed, status: " << status;
return ret;
}
AI_TALKVQE_CONFIG_S config = {0};
status = RK_MPI_AI_GetTalkVqeAttr(m_channel, &config);
if (status) {
LOG(error) << "RK_MPI_AI_GetTalkVqeAttr() failed, status: " << status;
return ret;
}
// LOG(info) << "param file: " << config.aParamFilePath;
config.s32WorkSampleRate = format.sampleRate;
config.s32FrameSample = format.sampleRate / 1000 * format.period;
config.u32OpenMask = AI_TALKVQE_MASK_AEC | AI_TALKVQE_MASK_ANR | AI_TALKVQE_MASK_AGC;
strncpy(config.aParamFilePath, ParamFilePath, sizeof(config.aParamFilePath));
RK_MPI_AI_SetTalkVqeAttr(m_channel, &config);
fprintf(stderr, "end\n");
if (status) {
LOG(error) << "RK_MPI_AI_SetTalkVqeAttr() failed, status: " << status;
return ret;
}
status = RK_MPI_AI_EnableVqe(m_channel);
if (status) {
LOG(error) << "RK_MPI_AI_EnableVqe() failed, status: " << status;
return ret;
}
status = RK_MPI_AI_StartStream(0);
if (status) {
LOG(info) << "start AI failed, status: " << status;
return ret;
}
m_exit = false;
m_thread = std::thread(&Input::run, this);
ret = true;
return ret;
}
void Input::stop() {
m_exit = true;
if (m_thread.joinable()) m_thread.join();
if (m_channel >= 0) {
RK_MPI_AI_DisableVqe(m_channel);
RK_MPI_AI_DisableChn(m_channel);
m_channel = -1;
}
}
void Input::setDataCallback(const ReadCallback &callback) {
m_callback = callback;
}
void Input::run() {
while (!m_exit) {
auto mediaBuffer = RK_MPI_SYS_GetMediaBuffer(RK_ID_AI, 0, -1);
if (!mediaBuffer) {
LOG(error) << "RK_MPI_SYS_GetMediaBuffer() failed.";
continue;
}
if (m_callback) {
Frame frame;
frame.data = reinterpret_cast<uint8_t *>(RK_MPI_MB_GetPtr(mediaBuffer));
frame.byteSize = RK_MPI_MB_GetSize(mediaBuffer);
frame.frameSize = frame.byteSize / m_format.channels / sizeof(uint16_t);
frame.timestamp = std::chrono::system_clock::now();
m_callback(frame);
}
RK_MPI_MB_ReleaseBuffer(mediaBuffer);
}
}
Output::Output() {
}
Output::~Output() {
close();
}
bool Output::open(uint32_t sampleSize, uint32_t sampleRate, uint32_t channels) {
m_channel = 0;
AO_CHN_ATTR_S parameter = {0};
parameter.pcAudioNode = "default";
parameter.enSampleFormat = RK_SAMPLE_FMT_S16;
parameter.u32NbSamples = sampleRate / 1000 * 20;
parameter.u32SampleRate = sampleRate;
parameter.u32Channels = channels;
RK_MPI_AO_SetChnAttr(m_channel, &parameter);
RK_MPI_AO_EnableChn(m_channel);
AO_VQE_CONFIG_S config = {0};
config.s32WorkSampleRate = sampleRate;
config.s32FrameSample = parameter.u32NbSamples;
config.u32OpenMask = AO_VQE_MASK_ANR | AO_VQE_MASK_AGC;
strncpy(config.aParamFilePath, ParamFilePath, sizeof(config.aParamFilePath));
RK_MPI_AO_SetVqeAttr(m_channel, &config);
RK_MPI_AO_EnableVqe(m_channel);
return true;
}
void Output::close() {
if (m_channel >= 0) {
RK_MPI_AO_DisableVqe(m_channel);
RK_MPI_AO_DisableChn(m_channel);
m_channel = -1;
}
}
void Output::write(const uint8_t *data, uint32_t byteSize) {
if (m_channel < 0) return;
auto buffer = RK_MPI_MB_CreateAudioBuffer(byteSize, RK_FALSE);
if (buffer != nullptr) {
memcpy(RK_MPI_MB_GetPtr(buffer), data, byteSize);
RK_MPI_MB_SetSize(buffer, byteSize);
RK_MPI_SYS_SendMediaBuffer(RK_ID_AO, m_channel, buffer);
RK_MPI_MB_ReleaseBuffer(buffer);
} else {
LOG(error) << "RK_MPI_MB_CreateAudioBuffer() failed.";
}
}
} // namespace RkAudio