From 66c1663495001558bc38af866007e18b6e555518 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sun, 6 Sep 2026 14:16:27 +0400 Subject: [PATCH] audio: use the shared AAC decoder for Audiodec --- src/libs/libAudio.cpp | 86 +++++++++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 20 deletions(-) diff --git a/src/libs/libAudio.cpp b/src/libs/libAudio.cpp index 2f91f2b18..8199ff933 100644 --- a/src/libs/libAudio.cpp +++ b/src/libs/libAudio.cpp @@ -1,4 +1,5 @@ #include "common/abi.h" +#include "libs/ajm/aac_decoder.h" #include "libs/audio.h" #include "libs/libs.h" #include "loader/symbolDatabase.h" @@ -6,6 +7,7 @@ #include #include #include +#include namespace Libs { @@ -622,6 +624,7 @@ namespace LibAudiodec { LIB_VERSION("Audiodec", 1, "Audiodec", 1, 1); +static constexpr int32_t AUDIODEC_ERROR_API_FAIL = -2139160576; // 0x807F0000 static constexpr int32_t AUDIODEC_ERROR_INVALID_TYPE = -2139160575; // 0x807F0001 static constexpr int32_t AUDIODEC_ERROR_ARG = -2139160574; // 0x807F0002 static constexpr int32_t AUDIODEC_ERROR_INVALID_PARAM_SIZE = -2139160572; // 0x807F0004 @@ -652,8 +655,9 @@ static constexpr uint32_t AUDIODEC_AT9_MAX_FRAME_SIZE = 2048; static constexpr uint32_t AUDIODEC_AT9_MAX_FRAME_SAMPLES = 256; static constexpr uint32_t AUDIODEC_MP3_MAX_FRAME_SIZE = 1441; static constexpr uint32_t AUDIODEC_MP3_MAX_FRAME_SAMPLES = 1152; -static constexpr uint32_t AUDIODEC_M4AAC_MAX_FRAME_SIZE = 4608; -static constexpr uint32_t AUDIODEC_M4AAC_MAX_FRAME_SAMPLES = 2048; + +static constexpr int32_t AUDIODEC_M4AAC_RESULT_DECODE_ERROR = -4; +static constexpr int32_t AUDIODEC_M4AAC_RESULT_INSUFFICIENT_DATA = -5; struct AudiodecAuInfo { uint32_t uiSize; @@ -719,6 +723,13 @@ struct AudiodecParamM4aac { uint32_t uiEnableHeaac; }; +struct AudiodecParamM4aacEx { + AudiodecParamM4aac base; + uint32_t uiEnableNondelayOutput; +}; + +static_assert(sizeof(AudiodecParamM4aacEx) == 28); + struct AudiodecM4aacInfo { uint32_t uiSize; uint32_t uiSamplingFreq; @@ -735,6 +746,7 @@ struct AudiodecDecoder { uint32_t sample_rate = 48000; uint32_t frame_bytes = AUDIODEC_MP3_MAX_FRAME_SIZE; uint32_t frame_samples = AUDIODEC_MP3_MAX_FRAME_SAMPLES; + std::unique_ptr aac; }; static Common::Mutex g_audiodec_mutex; @@ -750,12 +762,6 @@ static bool audiodec_is_valid_type(uint32_t codec_type) { } } -static uint32_t audiodec_sample_rate_from_index(uint32_t index) { - static constexpr std::array rates = {96000, 88200, 64000, 48000, 44100, 32000, - 24000, 22050, 16000, 12000, 11025, 8000}; - return index < rates.size() ? rates[index] : 48000; -} - static int32_t audiodec_word_size_bytes(int32_t word_size) { switch (word_size) { case AUDIODEC_WORD_SZ_24BIT: return 4; @@ -881,9 +887,10 @@ static void audiodec_fill_info(AudiodecCtrl* ctrl, const AudiodecDecoder& decode break; } case AUDIODEC_TYPE_M4AAC: { + const auto format = decoder.aac->GetFormat(); auto* info = static_cast(ctrl->pBsiInfo); - info->uiSamplingFreq = decoder.sample_rate; - info->uiNumberOfChannels = decoder.channels; + info->uiSamplingFreq = format.sampling_frequency; + info->uiNumberOfChannels = format.channel_num; info->uiHeaac = 0; info->iResult = 0; break; @@ -963,16 +970,28 @@ static int32_t KYTY_SYSV_ABI AudiodecCreateDecoder(AudiodecCtrl* ctrl, uint32_t break; } case AUDIODEC_TYPE_M4AAC: { - auto* param = static_cast(ctrl->pParam); - decoder.word_size = param->iBwPcm; - decoder.channels = param->uiMaxChannels == 0 ? 2 : param->uiMaxChannels; - if (decoder.channels > 8) { - decoder.channels = 8; + using namespace Audio::Ajm; + const auto* param = static_cast(ctrl->pParam); + const auto channels = + std::min(param->uiMaxChannels == 0 ? 2u : param->uiMaxChannels, 8u); + const auto encoding = param->iBwPcm == AUDIODEC_WORD_SZ_16BIT + ? AjmSampleEncoding::S16 + : param->iBwPcm == AUDIODEC_WORD_SZ_FLOAT + ? AjmSampleEncoding::Float : AjmSampleEncoding::S32; + uint64_t flags = param->uiEnableHeaac != 0 + ? AJM_INSTANCE_FLAG_DEC_M4AAC_ENABLE_SBR_DECODE : 0; + if (param->uiSize >= sizeof(AudiodecParamM4aacEx) && + static_cast(ctrl->pParam)->uiEnableNondelayOutput != 0) { + flags |= AJM_INSTANCE_FLAG_DEC_M4AAC_ENABLE_NONDELAY_OUTPUT; + } + decoder.aac = std::make_unique( + channels, decoder.sample_rate, encoding, flags); + const AjmDecM4aacInitializeParameters params { + param->uiConfigNumber, param->uiSamplingFreqIndex}; + if (decoder.aac->Initialize(¶ms, sizeof(params)).result != 0) { + decoder = {}; + return AUDIODEC_ERROR_API_FAIL; } - decoder.sample_rate = - audiodec_sample_rate_from_index(param->uiSamplingFreqIndex); - decoder.frame_bytes = AUDIODEC_M4AAC_MAX_FRAME_SIZE; - decoder.frame_samples = AUDIODEC_M4AAC_MAX_FRAME_SAMPLES; break; } } @@ -1022,6 +1041,29 @@ static int32_t KYTY_SYSV_ABI AudiodecDecode(int32_t handle, AudiodecCtrl* ctrl) return ret; } + if (decoder.aac) { + using namespace Audio::Ajm; + const auto result = decoder.aac->Decode( + ctrl->pAuInfo->pAuAddr, ctrl->pAuInfo->uiAuSize, ctrl->pPcmItem->pPcmAddr, + ctrl->pPcmItem->uiPcmSize, false, nullptr); + ctrl->pAuInfo->uiAuSize = static_cast(result.input_consumed); + ctrl->pPcmItem->uiPcmSize = static_cast(result.output_written); + audiodec_fill_info(ctrl, decoder); + auto* info = static_cast(ctrl->pBsiInfo); + info->iResult = (result.result & AJM_RESULT_CODEC_ERROR) != 0 + ? AUDIODEC_M4AAC_RESULT_DECODE_ERROR + : (result.result & AJM_RESULT_PARTIAL_INPUT) != 0 + ? AUDIODEC_M4AAC_RESULT_INSUFFICIENT_DATA : 0; + if ((result.result & AJM_RESULT_INVALID_PARAMETER) != 0) { + return AUDIODEC_ERROR_ARG; + } + if ((result.result & AJM_RESULT_FATAL) != 0) { + return AUDIODEC_ERROR_API_FAIL; + } + return (result.result & AJM_RESULT_NOT_ENOUGH_ROOM) != 0 + ? AUDIODEC_ERROR_INVALID_PCM_SIZE : 0; + } + const uint32_t word_bytes = static_cast(audiodec_word_size_bytes(decoder.word_size)); const uint32_t wanted_pcm = decoder.frame_samples * decoder.channels * word_bytes; const uint32_t produced_pcm = @@ -1046,9 +1088,13 @@ static int32_t KYTY_SYSV_ABI AudiodecClearContext(int32_t handle) { } Common::LockGuard lock(g_audiodec_mutex); - if (!g_audiodec_decoders[static_cast(handle - 1)].used) { + auto& decoder = g_audiodec_decoders[static_cast(handle - 1)]; + if (!decoder.used) { return AUDIODEC_ERROR_INVALID_HANDLE; } + if (decoder.aac) { + decoder.aac->Reset(); + } return 0; }