mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-06 00:04:59 -06:00
Merge remote-tracking branch 'origin/main' into user_and_settings
This commit is contained in:
commit
51279df16e
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -120,3 +120,6 @@
|
|||||||
[submodule "externals/miniz"]
|
[submodule "externals/miniz"]
|
||||||
path = externals/miniz
|
path = externals/miniz
|
||||||
url = https://github.com/richgel999/miniz
|
url = https://github.com/richgel999/miniz
|
||||||
|
[submodule "externals/aacdec/fdk-aac"]
|
||||||
|
path = externals/aacdec/fdk-aac
|
||||||
|
url = https://android.googlesource.com/platform/external/aac
|
||||||
|
|||||||
@ -262,6 +262,8 @@ include_directories(src)
|
|||||||
|
|
||||||
set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
||||||
src/core/libraries/ajm/ajm.h
|
src/core/libraries/ajm/ajm.h
|
||||||
|
src/core/libraries/ajm/ajm_aac.cpp
|
||||||
|
src/core/libraries/ajm/ajm_aac.h
|
||||||
src/core/libraries/ajm/ajm_at9.cpp
|
src/core/libraries/ajm/ajm_at9.cpp
|
||||||
src/core/libraries/ajm/ajm_at9.h
|
src/core/libraries/ajm/ajm_at9.h
|
||||||
src/core/libraries/ajm/ajm_batch.cpp
|
src/core/libraries/ajm/ajm_batch.cpp
|
||||||
@ -1089,7 +1091,7 @@ create_target_directory_groups(shadps4)
|
|||||||
|
|
||||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
||||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 SDL3_mixer::SDL3_mixer pugixml::pugixml)
|
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 SDL3_mixer::SDL3_mixer pugixml::pugixml)
|
||||||
target_link_libraries(shadps4 PRIVATE stb::headers libusb::usb lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json miniz)
|
target_link_libraries(shadps4 PRIVATE stb::headers libusb::usb lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json miniz fdk-aac)
|
||||||
|
|
||||||
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
||||||
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
||||||
|
|||||||
4
externals/CMakeLists.txt
vendored
4
externals/CMakeLists.txt
vendored
@ -258,6 +258,10 @@ if (WIN32)
|
|||||||
add_subdirectory(ext-wepoll)
|
add_subdirectory(ext-wepoll)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (NOT TARGET fdk-aac)
|
||||||
|
add_subdirectory(aacdec)
|
||||||
|
endif()
|
||||||
|
|
||||||
#nlohmann json
|
#nlohmann json
|
||||||
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
||||||
add_subdirectory(json)
|
add_subdirectory(json)
|
||||||
|
|||||||
154
externals/aacdec/CMakeLists.txt
vendored
Normal file
154
externals/aacdec/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
# SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
set(AACDEC_SRC
|
||||||
|
fdk-aac/libAACdec/src/FDK_delay.cpp
|
||||||
|
fdk-aac/libAACdec/src/aac_ram.cpp
|
||||||
|
fdk-aac/libAACdec/src/aac_rom.cpp
|
||||||
|
fdk-aac/libAACdec/src/aacdec_drc.cpp
|
||||||
|
fdk-aac/libAACdec/src/aacdec_hcr.cpp
|
||||||
|
fdk-aac/libAACdec/src/aacdec_hcr_bit.cpp
|
||||||
|
fdk-aac/libAACdec/src/aacdec_hcrs.cpp
|
||||||
|
fdk-aac/libAACdec/src/aacdec_pns.cpp
|
||||||
|
fdk-aac/libAACdec/src/aacdec_tns.cpp
|
||||||
|
fdk-aac/libAACdec/src/aacdecoder.cpp
|
||||||
|
fdk-aac/libAACdec/src/aacdecoder_lib.cpp
|
||||||
|
fdk-aac/libAACdec/src/block.cpp
|
||||||
|
fdk-aac/libAACdec/src/channel.cpp
|
||||||
|
fdk-aac/libAACdec/src/channelinfo.cpp
|
||||||
|
fdk-aac/libAACdec/src/conceal.cpp
|
||||||
|
fdk-aac/libAACdec/src/ldfiltbank.cpp
|
||||||
|
fdk-aac/libAACdec/src/pulsedata.cpp
|
||||||
|
fdk-aac/libAACdec/src/rvlc.cpp
|
||||||
|
fdk-aac/libAACdec/src/rvlcbit.cpp
|
||||||
|
fdk-aac/libAACdec/src/rvlcconceal.cpp
|
||||||
|
fdk-aac/libAACdec/src/stereo.cpp
|
||||||
|
fdk-aac/libAACdec/src/usacdec_ace_d4t64.cpp
|
||||||
|
fdk-aac/libAACdec/src/usacdec_ace_ltp.cpp
|
||||||
|
fdk-aac/libAACdec/src/usacdec_acelp.cpp
|
||||||
|
fdk-aac/libAACdec/src/usacdec_fac.cpp
|
||||||
|
fdk-aac/libAACdec/src/usacdec_lpc.cpp
|
||||||
|
fdk-aac/libAACdec/src/usacdec_lpd.cpp
|
||||||
|
fdk-aac/libAACdec/src/usacdec_rom.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(FDK_SRC
|
||||||
|
fdk-aac/libFDK/src/FDK_bitbuffer.cpp
|
||||||
|
fdk-aac/libFDK/src/FDK_core.cpp
|
||||||
|
fdk-aac/libFDK/src/FDK_crc.cpp
|
||||||
|
fdk-aac/libFDK/src/FDK_decorrelate.cpp
|
||||||
|
fdk-aac/libFDK/src/FDK_hybrid.cpp
|
||||||
|
fdk-aac/libFDK/src/FDK_lpc.cpp
|
||||||
|
fdk-aac/libFDK/src/FDK_matrixCalloc.cpp
|
||||||
|
fdk-aac/libFDK/src/FDK_qmf_domain.cpp
|
||||||
|
fdk-aac/libFDK/src/FDK_tools_rom.cpp
|
||||||
|
fdk-aac/libFDK/src/FDK_trigFcts.cpp
|
||||||
|
fdk-aac/libFDK/src/autocorr2nd.cpp
|
||||||
|
fdk-aac/libFDK/src/dct.cpp
|
||||||
|
fdk-aac/libFDK/src/fft.cpp
|
||||||
|
fdk-aac/libFDK/src/fft_rad2.cpp
|
||||||
|
fdk-aac/libFDK/src/fixpoint_math.cpp
|
||||||
|
fdk-aac/libFDK/src/huff_nodes.cpp
|
||||||
|
fdk-aac/libFDK/src/mdct.cpp
|
||||||
|
fdk-aac/libFDK/src/nlc_dec.cpp
|
||||||
|
fdk-aac/libFDK/src/qmf.cpp
|
||||||
|
fdk-aac/libFDK/src/scale.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SYS_SRC
|
||||||
|
fdk-aac/libSYS/src/genericStds.cpp
|
||||||
|
fdk-aac/libSYS/src/syslib_channelMapDescr.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(ARITHCODING_SRC
|
||||||
|
fdk-aac/libArithCoding/src/ac_arith_coder.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(MPEGTPDEC_SRC
|
||||||
|
fdk-aac/libMpegTPDec/src/tpdec_adif.cpp
|
||||||
|
fdk-aac/libMpegTPDec/src/tpdec_adts.cpp
|
||||||
|
fdk-aac/libMpegTPDec/src/tpdec_asc.cpp
|
||||||
|
fdk-aac/libMpegTPDec/src/tpdec_drm.cpp
|
||||||
|
fdk-aac/libMpegTPDec/src/tpdec_latm.cpp
|
||||||
|
fdk-aac/libMpegTPDec/src/tpdec_lib.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SBRDEC_SRC
|
||||||
|
fdk-aac/libSBRdec/src/HFgen_preFlat.cpp
|
||||||
|
fdk-aac/libSBRdec/src/env_calc.cpp
|
||||||
|
fdk-aac/libSBRdec/src/env_dec.cpp
|
||||||
|
fdk-aac/libSBRdec/src/env_extr.cpp
|
||||||
|
fdk-aac/libSBRdec/src/hbe.cpp
|
||||||
|
fdk-aac/libSBRdec/src/huff_dec.cpp
|
||||||
|
fdk-aac/libSBRdec/src/lpp_tran.cpp
|
||||||
|
fdk-aac/libSBRdec/src/psbitdec.cpp
|
||||||
|
fdk-aac/libSBRdec/src/psdec.cpp
|
||||||
|
fdk-aac/libSBRdec/src/psdec_drm.cpp
|
||||||
|
fdk-aac/libSBRdec/src/psdecrom_drm.cpp
|
||||||
|
fdk-aac/libSBRdec/src/pvc_dec.cpp
|
||||||
|
fdk-aac/libSBRdec/src/sbr_deb.cpp
|
||||||
|
fdk-aac/libSBRdec/src/sbr_dec.cpp
|
||||||
|
fdk-aac/libSBRdec/src/sbr_ram.cpp
|
||||||
|
fdk-aac/libSBRdec/src/sbr_rom.cpp
|
||||||
|
fdk-aac/libSBRdec/src/sbrdec_drc.cpp
|
||||||
|
fdk-aac/libSBRdec/src/sbrdec_freq_sca.cpp
|
||||||
|
fdk-aac/libSBRdec/src/sbrdecoder.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(PCMUTILS_SRC
|
||||||
|
fdk-aac/libPCMutils/src/limiter.cpp
|
||||||
|
fdk-aac/libPCMutils/src/pcm_utils.cpp
|
||||||
|
fdk-aac/libPCMutils/src/pcmdmx_lib.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(DRCDEC_SRC
|
||||||
|
fdk-aac/libDRCdec/src/FDK_drcDecLib.cpp
|
||||||
|
fdk-aac/libDRCdec/src/drcDec_gainDecoder.cpp
|
||||||
|
fdk-aac/libDRCdec/src/drcDec_reader.cpp
|
||||||
|
fdk-aac/libDRCdec/src/drcDec_rom.cpp
|
||||||
|
fdk-aac/libDRCdec/src/drcDec_selectionProcess.cpp
|
||||||
|
fdk-aac/libDRCdec/src/drcDec_tools.cpp
|
||||||
|
fdk-aac/libDRCdec/src/drcGainDec_init.cpp
|
||||||
|
fdk-aac/libDRCdec/src/drcGainDec_preprocess.cpp
|
||||||
|
fdk-aac/libDRCdec/src/drcGainDec_process.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(SACDEC_SRC
|
||||||
|
fdk-aac/libSACdec/src/sac_bitdec.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_calcM1andM2.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_dec.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_dec_conceal.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_dec_lib.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_process.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_qmf.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_reshapeBBEnv.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_rom.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_smoothing.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_stp.cpp
|
||||||
|
fdk-aac/libSACdec/src/sac_tsd.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(fdk-aac
|
||||||
|
${AACDEC_SRC}
|
||||||
|
${FDK_SRC}
|
||||||
|
${SYS_SRC}
|
||||||
|
${ARITHCODING_SRC}
|
||||||
|
${MPEGTPDEC_SRC}
|
||||||
|
${SBRDEC_SRC}
|
||||||
|
${PCMUTILS_SRC}
|
||||||
|
${DRCDEC_SRC}
|
||||||
|
${SACDEC_SRC}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(fdk-aac
|
||||||
|
PUBLIC
|
||||||
|
fdk-aac/libAACdec/include
|
||||||
|
fdk-aac/libFDK/include
|
||||||
|
fdk-aac/libSYS/include
|
||||||
|
fdk-aac/libArithCoding/include
|
||||||
|
fdk-aac/libMpegTPDec/include
|
||||||
|
fdk-aac/libSBRdec/include
|
||||||
|
fdk-aac/libPCMutils/include
|
||||||
|
fdk-aac/libDRCdec/include
|
||||||
|
fdk-aac/libSACdec/include
|
||||||
|
)
|
||||||
1
externals/aacdec/fdk-aac
vendored
Submodule
1
externals/aacdec/fdk-aac
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit ee76460efbdb147e26d804c798949c23f174460b
|
||||||
@ -144,9 +144,8 @@ int PS4_SYSV_ABI sceAjmInitialize(s64 reserved, u32* p_context_id) {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceAjmInstanceCodecType() {
|
AjmCodecType PS4_SYSV_ABI sceAjmInstanceCodecType(u32 instance_id) {
|
||||||
LOG_ERROR(Lib_Ajm, "(STUBBED) called");
|
return static_cast<AjmCodecType>((instance_id >> 14) & 0x1F);
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceAjmInstanceCreate(u32 context_id, AjmCodecType codec_type,
|
int PS4_SYSV_ABI sceAjmInstanceCreate(u32 context_id, AjmCodecType codec_type,
|
||||||
|
|||||||
@ -82,8 +82,6 @@ enum class AjmStatisticsFlags : u64 {
|
|||||||
DECLARE_ENUM_FLAG_OPERATORS(AjmStatisticsFlags)
|
DECLARE_ENUM_FLAG_OPERATORS(AjmStatisticsFlags)
|
||||||
|
|
||||||
union AjmStatisticsJobFlags {
|
union AjmStatisticsJobFlags {
|
||||||
AjmStatisticsJobFlags(AjmJobFlags job_flags) : raw(job_flags.raw) {}
|
|
||||||
|
|
||||||
u64 raw;
|
u64 raw;
|
||||||
struct {
|
struct {
|
||||||
u64 version : 3;
|
u64 version : 3;
|
||||||
@ -217,7 +215,7 @@ int PS4_SYSV_ABI sceAjmDecMp3ParseFrame(const u8* stream, u32 stream_size, int p
|
|||||||
AjmDecMp3ParseFrame* frame);
|
AjmDecMp3ParseFrame* frame);
|
||||||
int PS4_SYSV_ABI sceAjmFinalize();
|
int PS4_SYSV_ABI sceAjmFinalize();
|
||||||
int PS4_SYSV_ABI sceAjmInitialize(s64 reserved, u32* out_context);
|
int PS4_SYSV_ABI sceAjmInitialize(s64 reserved, u32* out_context);
|
||||||
int PS4_SYSV_ABI sceAjmInstanceCodecType();
|
AjmCodecType PS4_SYSV_ABI sceAjmInstanceCodecType(u32 instance_id);
|
||||||
int PS4_SYSV_ABI sceAjmInstanceCreate(u32 context, AjmCodecType codec_type, AjmInstanceFlags flags,
|
int PS4_SYSV_ABI sceAjmInstanceCreate(u32 context, AjmCodecType codec_type, AjmInstanceFlags flags,
|
||||||
u32* instance);
|
u32* instance);
|
||||||
int PS4_SYSV_ABI sceAjmInstanceDestroy(u32 context, u32 instance);
|
int PS4_SYSV_ABI sceAjmInstanceDestroy(u32 context, u32 instance);
|
||||||
|
|||||||
194
src/core/libraries/ajm/ajm_aac.cpp
Normal file
194
src/core/libraries/ajm/ajm_aac.cpp
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ajm.h"
|
||||||
|
#include "ajm_aac.h"
|
||||||
|
#include "ajm_result.h"
|
||||||
|
|
||||||
|
// using this internal header to manually configure the decoder in RAW mode
|
||||||
|
#include "externals/aacdec/fdk-aac/libAACdec/src/aacdecoder.h"
|
||||||
|
|
||||||
|
#include <aacdecoder_lib.h>
|
||||||
|
#include <magic_enum/magic_enum.hpp>
|
||||||
|
|
||||||
|
namespace Libraries::Ajm {
|
||||||
|
|
||||||
|
AjmAacDecoder::AjmAacDecoder(AjmFormatEncoding format, AjmAacCodecFlags flags, u32 channels)
|
||||||
|
: m_format(format), m_flags(flags), m_channels(channels), m_pcm_buffer(2048 * 8),
|
||||||
|
m_skip_frames(True(flags & AjmAacCodecFlags::EnableNondelayOutput) ? 0 : 2) {}
|
||||||
|
|
||||||
|
AjmAacDecoder::~AjmAacDecoder() {
|
||||||
|
aacDecoder_Close(m_decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
TRANSPORT_TYPE TransportTypeFromConfigType(ConfigType config_type) {
|
||||||
|
switch (config_type) {
|
||||||
|
case ConfigType::ADTS:
|
||||||
|
return TT_MP4_ADTS;
|
||||||
|
case ConfigType::RAW:
|
||||||
|
return TT_MP4_RAW;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static UINT g_freq[] = {
|
||||||
|
96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000,
|
||||||
|
};
|
||||||
|
|
||||||
|
void AjmAacDecoder::Reset() {
|
||||||
|
if (m_decoder) {
|
||||||
|
aacDecoder_Close(m_decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_decoder = aacDecoder_Open(TransportTypeFromConfigType(m_init_params.config_type), 1);
|
||||||
|
if (m_init_params.config_type == ConfigType::RAW) {
|
||||||
|
// Manually configure the decoder
|
||||||
|
// Things may be incorrect due to limited documentation
|
||||||
|
CSAudioSpecificConfig asc{};
|
||||||
|
asc.m_aot = AOT_AAC_LC;
|
||||||
|
asc.m_samplingFrequency = g_freq[m_init_params.sampling_freq_type];
|
||||||
|
asc.m_samplingFrequencyIndex = m_init_params.sampling_freq_type;
|
||||||
|
asc.m_samplesPerFrame = 1024;
|
||||||
|
asc.m_epConfig = -1;
|
||||||
|
switch (m_channels) {
|
||||||
|
case 0:
|
||||||
|
asc.m_channelConfiguration = 2;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
asc.m_channelConfiguration = m_channels;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
asc.m_channelConfiguration = 11;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
asc.m_channelConfiguration = 12; // 7, 12 or 14 ?
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
UCHAR changed = 1;
|
||||||
|
CAacDecoder_Init(m_decoder, &asc, AC_CM_ALLOC_MEM, &changed);
|
||||||
|
}
|
||||||
|
m_skip_frames = True(m_flags & AjmAacCodecFlags::EnableNondelayOutput) ? 0 : 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AjmAacDecoder::Initialize(const void* buffer, u32 buffer_size) {
|
||||||
|
ASSERT(buffer_size == 8);
|
||||||
|
m_init_params = *reinterpret_cast<const InitializeParameters*>(buffer);
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AjmAacDecoder::GetInfo(void* out_info) const {
|
||||||
|
auto* codec_info = reinterpret_cast<AjmSidebandDecM4aacCodecInfo*>(out_info);
|
||||||
|
*codec_info = {
|
||||||
|
.heaac = True(m_flags & AjmAacCodecFlags::EnableSbrDecode),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
AjmSidebandFormat AjmAacDecoder::GetFormat() const {
|
||||||
|
const auto* const info = aacDecoder_GetStreamInfo(m_decoder);
|
||||||
|
return {
|
||||||
|
.num_channels = static_cast<u32>(info->numChannels),
|
||||||
|
.channel_mask = GetChannelMask(info->numChannels),
|
||||||
|
.sampl_freq = static_cast<u32>(info->sampleRate),
|
||||||
|
.sample_encoding = m_format, // AjmFormatEncoding
|
||||||
|
.bitrate = static_cast<u32>(info->bitRate),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 AjmAacDecoder::GetMinimumInputSize() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 AjmAacDecoder::GetNextFrameSize(const AjmInstanceGapless& gapless) const {
|
||||||
|
const auto* const info = aacDecoder_GetStreamInfo(m_decoder);
|
||||||
|
if (info->aacSamplesPerFrame <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const auto skip_samples = std::min<u32>(gapless.current.skip_samples, info->frameSize);
|
||||||
|
const auto samples =
|
||||||
|
gapless.init.total_samples != 0
|
||||||
|
? std::min<u32>(gapless.current.total_samples, info->frameSize - skip_samples)
|
||||||
|
: info->frameSize - skip_samples;
|
||||||
|
return samples * info->numChannels * GetPCMSize(m_format);
|
||||||
|
}
|
||||||
|
|
||||||
|
DecoderResult AjmAacDecoder::ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||||
|
AjmInstanceGapless& gapless) {
|
||||||
|
DecoderResult result{};
|
||||||
|
|
||||||
|
// Discard the previous contents of the internal buffer and replace them with new ones
|
||||||
|
aacDecoder_SetParam(m_decoder, AAC_TPDEC_CLEAR_BUFFER, 1);
|
||||||
|
UCHAR* buffers[] = {input.data()};
|
||||||
|
const UINT sizes[] = {static_cast<UINT>(input.size())};
|
||||||
|
UINT valid = sizes[0];
|
||||||
|
aacDecoder_Fill(m_decoder, buffers, sizes, &valid);
|
||||||
|
auto ret = aacDecoder_DecodeFrame(m_decoder, reinterpret_cast<s16*>(m_pcm_buffer.data()),
|
||||||
|
m_pcm_buffer.size() / 2, 0);
|
||||||
|
|
||||||
|
switch (ret) {
|
||||||
|
case AAC_DEC_OK:
|
||||||
|
break;
|
||||||
|
case AAC_DEC_NOT_ENOUGH_BITS:
|
||||||
|
result.result = ORBIS_AJM_RESULT_PARTIAL_INPUT;
|
||||||
|
return result;
|
||||||
|
default:
|
||||||
|
LOG_ERROR(Lib_Ajm, "aacDecoder_DecodeFrame failed ret = {:#x}", static_cast<u32>(ret));
|
||||||
|
result.result = ORBIS_AJM_RESULT_CODEC_ERROR | ORBIS_AJM_RESULT_FATAL;
|
||||||
|
result.internal_result = ret;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* const info = aacDecoder_GetStreamInfo(m_decoder);
|
||||||
|
auto bytes_used = info->numTotalBytes;
|
||||||
|
|
||||||
|
result.frames_decoded += 1;
|
||||||
|
input = input.subspan(bytes_used);
|
||||||
|
|
||||||
|
if (m_skip_frames > 0) {
|
||||||
|
--m_skip_frames;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 skip_samples = 0;
|
||||||
|
if (gapless.current.skip_samples > 0) {
|
||||||
|
skip_samples = std::min<u16>(info->frameSize, gapless.current.skip_samples);
|
||||||
|
gapless.current.skip_samples -= skip_samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto max_samples =
|
||||||
|
gapless.init.total_samples != 0 ? gapless.current.total_samples : info->aacSamplesPerFrame;
|
||||||
|
|
||||||
|
size_t pcm_written = 0;
|
||||||
|
switch (m_format) {
|
||||||
|
case AjmFormatEncoding::S16:
|
||||||
|
pcm_written = WriteOutputSamples<s16>(output, skip_samples * info->numChannels,
|
||||||
|
max_samples * info->numChannels);
|
||||||
|
break;
|
||||||
|
case AjmFormatEncoding::S32:
|
||||||
|
UNREACHABLE_MSG("NOT IMPLEMENTED");
|
||||||
|
break;
|
||||||
|
case AjmFormatEncoding::Float:
|
||||||
|
UNREACHABLE_MSG("NOT IMPLEMENTED");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.samples_written = pcm_written / info->numChannels;
|
||||||
|
gapless.current.skipped_samples += info->frameSize - result.samples_written;
|
||||||
|
if (gapless.init.total_samples != 0) {
|
||||||
|
gapless.current.total_samples -= result.samples_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Libraries::Ajm
|
||||||
73
src/core/libraries/ajm/ajm_aac.h
Normal file
73
src/core/libraries/ajm/ajm_aac.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/enum.h"
|
||||||
|
#include "common/types.h"
|
||||||
|
#include "core/libraries/ajm/ajm_instance.h"
|
||||||
|
|
||||||
|
#include <span>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct AAC_DECODER_INSTANCE;
|
||||||
|
|
||||||
|
namespace Libraries::Ajm {
|
||||||
|
|
||||||
|
enum ConfigType : u32 {
|
||||||
|
ADTS = 1,
|
||||||
|
RAW = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum AjmAacCodecFlags : u32 {
|
||||||
|
EnableSbrDecode = 1 << 0,
|
||||||
|
EnableNondelayOutput = 1 << 1,
|
||||||
|
SurroundChannelInterleaveOrderExtlExtrLsRs = 1 << 2,
|
||||||
|
SurroundChannelInterleaveOrderLsRsExtlExtr = 1 << 3,
|
||||||
|
};
|
||||||
|
DECLARE_ENUM_FLAG_OPERATORS(AjmAacCodecFlags)
|
||||||
|
|
||||||
|
struct AjmSidebandDecM4aacCodecInfo {
|
||||||
|
u32 heaac;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AjmAacDecoder final : AjmCodec {
|
||||||
|
explicit AjmAacDecoder(AjmFormatEncoding format, AjmAacCodecFlags flags, u32 channels);
|
||||||
|
~AjmAacDecoder() override;
|
||||||
|
|
||||||
|
void Reset() override;
|
||||||
|
void Initialize(const void* buffer, u32 buffer_size) override;
|
||||||
|
void GetInfo(void* out_info) const override;
|
||||||
|
AjmSidebandFormat GetFormat() const override;
|
||||||
|
u32 GetMinimumInputSize() const override;
|
||||||
|
u32 GetNextFrameSize(const AjmInstanceGapless& gapless) const override;
|
||||||
|
DecoderResult ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||||
|
AjmInstanceGapless& gapless) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct InitializeParameters {
|
||||||
|
ConfigType config_type;
|
||||||
|
u32 sampling_freq_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
size_t WriteOutputSamples(SparseOutputBuffer& output, u32 skipped_pcm, u32 max_pcm) {
|
||||||
|
std::span<T> pcm_data{reinterpret_cast<T*>(m_pcm_buffer.data()),
|
||||||
|
m_pcm_buffer.size() / sizeof(T)};
|
||||||
|
pcm_data = pcm_data.subspan(skipped_pcm);
|
||||||
|
const auto pcm_size = std::min(u32(pcm_data.size()), max_pcm);
|
||||||
|
return output.Write(pcm_data.subspan(0, pcm_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
const AjmFormatEncoding m_format;
|
||||||
|
const AjmAacCodecFlags m_flags;
|
||||||
|
const u32 m_channels;
|
||||||
|
std::vector<u8> m_pcm_buffer;
|
||||||
|
|
||||||
|
u32 m_skip_frames = 0;
|
||||||
|
InitializeParameters m_init_params = {};
|
||||||
|
AAC_DECODER_INSTANCE* m_decoder = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Ajm
|
||||||
@ -54,7 +54,7 @@ struct RIFFHeader {
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(RIFFHeader) == 12);
|
static_assert(sizeof(RIFFHeader) == 12);
|
||||||
|
|
||||||
AjmAt9Decoder::AjmAt9Decoder(AjmFormatEncoding format, AjmAt9CodecFlags flags)
|
AjmAt9Decoder::AjmAt9Decoder(AjmFormatEncoding format, AjmAt9CodecFlags flags, u32)
|
||||||
: m_format(format), m_flags(flags), m_handle(Atrac9GetHandle()) {}
|
: m_format(format), m_flags(flags), m_handle(Atrac9GetHandle()) {}
|
||||||
|
|
||||||
AjmAt9Decoder::~AjmAt9Decoder() {
|
AjmAt9Decoder::~AjmAt9Decoder() {
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/enum.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "core/libraries/ajm/ajm_instance.h"
|
#include "core/libraries/ajm/ajm_instance.h"
|
||||||
|
|
||||||
@ -13,8 +14,6 @@
|
|||||||
|
|
||||||
namespace Libraries::Ajm {
|
namespace Libraries::Ajm {
|
||||||
|
|
||||||
constexpr s32 ORBIS_AJM_DEC_AT9_MAX_CHANNELS = 8;
|
|
||||||
|
|
||||||
enum AjmAt9CodecFlags : u32 {
|
enum AjmAt9CodecFlags : u32 {
|
||||||
ParseRiffHeader = 1 << 0,
|
ParseRiffHeader = 1 << 0,
|
||||||
NonInterleavedOutput = 1 << 8,
|
NonInterleavedOutput = 1 << 8,
|
||||||
@ -29,7 +28,7 @@ struct AjmSidebandDecAt9CodecInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct AjmAt9Decoder final : AjmCodec {
|
struct AjmAt9Decoder final : AjmCodec {
|
||||||
explicit AjmAt9Decoder(AjmFormatEncoding format, AjmAt9CodecFlags flags);
|
explicit AjmAt9Decoder(AjmFormatEncoding format, AjmAt9CodecFlags flags, u32 channels);
|
||||||
~AjmAt9Decoder() override;
|
~AjmAt9Decoder() override;
|
||||||
|
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
|
|||||||
@ -165,7 +165,7 @@ AjmJob AjmStatisticsJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buf
|
|||||||
ASSERT(job_flags.has_value());
|
ASSERT(job_flags.has_value());
|
||||||
job.flags = job_flags.value();
|
job.flags = job_flags.value();
|
||||||
|
|
||||||
AjmStatisticsJobFlags flags(job.flags);
|
AjmStatisticsJobFlags flags{.raw = job.flags.raw};
|
||||||
if (input_control_buffer.has_value()) {
|
if (input_control_buffer.has_value()) {
|
||||||
AjmBatchBuffer input_batch(input_control_buffer.value());
|
AjmBatchBuffer input_batch(input_control_buffer.value());
|
||||||
if (True(flags.statistics_flags & AjmStatisticsFlags::Engine)) {
|
if (True(flags.statistics_flags & AjmStatisticsFlags::Engine)) {
|
||||||
|
|||||||
@ -18,7 +18,8 @@
|
|||||||
|
|
||||||
namespace Libraries::Ajm {
|
namespace Libraries::Ajm {
|
||||||
|
|
||||||
static constexpr u32 ORBIS_AJM_WAIT_INFINITE = -1;
|
constexpr u32 ORBIS_AJM_WAIT_INFINITE = -1;
|
||||||
|
constexpr int INSTANCE_ID_MASK = 0x3FFF;
|
||||||
|
|
||||||
AjmContext::AjmContext() {
|
AjmContext::AjmContext() {
|
||||||
worker_thread = std::jthread([this](std::stop_token stop) { this->WorkerThread(stop); });
|
worker_thread = std::jthread([this](std::stop_token stop) { this->WorkerThread(stop); });
|
||||||
@ -84,7 +85,7 @@ void AjmContext::ProcessBatch(u32 id, std::span<AjmJob> jobs) {
|
|||||||
std::shared_ptr<AjmInstance> instance;
|
std::shared_ptr<AjmInstance> instance;
|
||||||
{
|
{
|
||||||
std::shared_lock lock(instances_mutex);
|
std::shared_lock lock(instances_mutex);
|
||||||
auto* p_instance = instances.Get(job.instance_id);
|
auto* p_instance = instances.Get(job.instance_id & INSTANCE_ID_MASK);
|
||||||
ASSERT_MSG(p_instance != nullptr, "Attempting to execute job on null instance");
|
ASSERT_MSG(p_instance != nullptr, "Attempting to execute job on null instance");
|
||||||
instance = *p_instance;
|
instance = *p_instance;
|
||||||
}
|
}
|
||||||
@ -176,15 +177,15 @@ s32 AjmContext::InstanceCreate(AjmCodecType codec_type, AjmInstanceFlags flags,
|
|||||||
if (!opt_index.has_value()) {
|
if (!opt_index.has_value()) {
|
||||||
return ORBIS_AJM_ERROR_OUT_OF_RESOURCES;
|
return ORBIS_AJM_ERROR_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
*out_instance = opt_index.value();
|
*out_instance = opt_index.value() | (static_cast<u32>(codec_type) << 14);
|
||||||
|
|
||||||
LOG_INFO(Lib_Ajm, "instance = {}", *out_instance);
|
LOG_INFO(Lib_Ajm, "instance = {}", *out_instance);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 AjmContext::InstanceDestroy(u32 instance) {
|
s32 AjmContext::InstanceDestroy(u32 instance_id) {
|
||||||
std::unique_lock lock(instances_mutex);
|
std::unique_lock lock(instances_mutex);
|
||||||
if (!instances.Destroy(instance)) {
|
if (!instances.Destroy(instance_id & INSTANCE_ID_MASK)) {
|
||||||
return ORBIS_AJM_ERROR_INVALID_INSTANCE;
|
return ORBIS_AJM_ERROR_INVALID_INSTANCE;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ajm_aac.h"
|
||||||
#include "ajm_at9.h"
|
#include "ajm_at9.h"
|
||||||
#include "ajm_instance.h"
|
#include "ajm_instance.h"
|
||||||
#include "ajm_mp3.h"
|
#include "ajm_mp3.h"
|
||||||
@ -26,13 +27,18 @@ u8 GetPCMSize(AjmFormatEncoding format) {
|
|||||||
AjmInstance::AjmInstance(AjmCodecType codec_type, AjmInstanceFlags flags) : m_flags(flags) {
|
AjmInstance::AjmInstance(AjmCodecType codec_type, AjmInstanceFlags flags) : m_flags(flags) {
|
||||||
switch (codec_type) {
|
switch (codec_type) {
|
||||||
case AjmCodecType::At9Dec: {
|
case AjmCodecType::At9Dec: {
|
||||||
m_codec = std::make_unique<AjmAt9Decoder>(AjmFormatEncoding(flags.format),
|
m_codec = std::make_unique<AjmAt9Decoder>(
|
||||||
AjmAt9CodecFlags(flags.codec));
|
AjmFormatEncoding(flags.format), AjmAt9CodecFlags(flags.codec), u32(flags.channels));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AjmCodecType::Mp3Dec: {
|
case AjmCodecType::Mp3Dec: {
|
||||||
m_codec = std::make_unique<AjmMp3Decoder>(AjmFormatEncoding(flags.format),
|
m_codec = std::make_unique<AjmMp3Decoder>(
|
||||||
AjmMp3CodecFlags(flags.codec));
|
AjmFormatEncoding(flags.format), AjmMp3CodecFlags(flags.codec), u32(flags.channels));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AjmCodecType::M4aacDec: {
|
||||||
|
m_codec = std::make_unique<AjmAacDecoder>(
|
||||||
|
AjmFormatEncoding(flags.format), AjmAacCodecFlags(flags.codec), u32(flags.channels));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -105,7 +105,7 @@ AVFrame* AjmMp3Decoder::ConvertAudioFrame(AVFrame* frame) {
|
|||||||
return new_frame;
|
return new_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
AjmMp3Decoder::AjmMp3Decoder(AjmFormatEncoding format, AjmMp3CodecFlags flags)
|
AjmMp3Decoder::AjmMp3Decoder(AjmFormatEncoding format, AjmMp3CodecFlags flags, u32)
|
||||||
: m_format(format), m_flags(flags), m_codec(avcodec_find_decoder(AV_CODEC_ID_MP3)),
|
: m_format(format), m_flags(flags), m_codec(avcodec_find_decoder(AV_CODEC_ID_MP3)),
|
||||||
m_codec_context(avcodec_alloc_context3(m_codec)), m_parser(av_parser_init(m_codec->id)) {
|
m_codec_context(avcodec_alloc_context3(m_codec)), m_parser(av_parser_init(m_codec->id)) {
|
||||||
int ret = avcodec_open2(m_codec_context, m_codec, nullptr);
|
int ret = avcodec_open2(m_codec_context, m_codec, nullptr);
|
||||||
@ -311,7 +311,8 @@ int AjmMp3Decoder::ParseMp3Header(const u8* p_begin, u32 stream_size, int parse_
|
|||||||
|
|
||||||
BitReader reader(p_current);
|
BitReader reader(p_current);
|
||||||
if (header->protection_type == 0) {
|
if (header->protection_type == 0) {
|
||||||
reader.Skip(16); // crc = reader.Read<u16>(16);
|
// crc = reader.Read<u16>(16);
|
||||||
|
reader.Skip(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header->version == Mp3AudioVersion::V1) {
|
if (header->version == Mp3AudioVersion::V1) {
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/enum.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "core/libraries/ajm/ajm_instance.h"
|
#include "core/libraries/ajm/ajm_instance.h"
|
||||||
|
|
||||||
@ -63,7 +64,7 @@ struct AjmSidebandDecMp3CodecInfo {
|
|||||||
|
|
||||||
class AjmMp3Decoder : public AjmCodec {
|
class AjmMp3Decoder : public AjmCodec {
|
||||||
public:
|
public:
|
||||||
explicit AjmMp3Decoder(AjmFormatEncoding format, AjmMp3CodecFlags flags);
|
explicit AjmMp3Decoder(AjmFormatEncoding format, AjmMp3CodecFlags flags, u32 channels);
|
||||||
~AjmMp3Decoder() override;
|
~AjmMp3Decoder() override;
|
||||||
|
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
|
|||||||
@ -192,7 +192,9 @@ int main(int argc, char* argv[]) {
|
|||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
if (!SDL_ShowSimpleMessageBox(
|
if (!SDL_ShowSimpleMessageBox(
|
||||||
SDL_MESSAGEBOX_INFORMATION, "shadPS4",
|
SDL_MESSAGEBOX_INFORMATION, "shadPS4",
|
||||||
"This is a CLI application. Please use the QTLauncher for a GUI.", nullptr))
|
"This is a CLI application. Please use the QTLauncher for a GUI: "
|
||||||
|
"https://github.com/shadps4-emu/shadps4-qtlauncher/releases",
|
||||||
|
nullptr))
|
||||||
std::cerr << "Could not display SDL message box! Error: " << SDL_GetError() << "\n";
|
std::cerr << "Could not display SDL message box! Error: " << SDL_GetError() << "\n";
|
||||||
int dummy = 0; // one does not simply pass 0 directly
|
int dummy = 0; // one does not simply pass 0 directly
|
||||||
arg_map.at("-h")(dummy);
|
arg_map.at("-h")(dummy);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user