mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-01-31 00:55:19 +01:00
Added libSceAudiodec to lle modules list (#3916)
* added libSceAudiodec to lle modules list * crappy float resample , use it at your own risk * clang * adjustments to aac --------- Co-authored-by: Vladislav Mikhalin <mikhalinvlad@gmail.com>
This commit is contained in:
@@ -150,7 +150,7 @@ The following firmware modules are supported and must be placed in shadPS4's `sy
|
|||||||
| libSceCesCs.sprx | libSceFont.sprx | libSceFontFt.sprx | libSceFreeTypeOt.sprx |
|
| libSceCesCs.sprx | libSceFont.sprx | libSceFontFt.sprx | libSceFreeTypeOt.sprx |
|
||||||
| libSceJpegDec.sprx | libSceJpegEnc.sprx | libSceJson.sprx | libSceJson2.sprx |
|
| libSceJpegDec.sprx | libSceJpegEnc.sprx | libSceJson.sprx | libSceJson2.sprx |
|
||||||
| libSceLibcInternal.sprx | libSceNgs2.sprx | libScePngEnc.sprx | libSceRtc.sprx |
|
| libSceLibcInternal.sprx | libSceNgs2.sprx | libScePngEnc.sprx | libSceRtc.sprx |
|
||||||
| libSceUlt.sprx | | | |
|
| libSceUlt.sprx | libSceAudiodec.sprx | | |
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
> [!Caution]
|
> [!Caution]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024-2026 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
@@ -34,7 +34,7 @@ u32 GetChannelMask(u32 num_channels) {
|
|||||||
case 8:
|
case 8:
|
||||||
return ORBIS_AJM_CHANNELMASK_7POINT1;
|
return ORBIS_AJM_CHANNELMASK_7POINT1;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE_MSG("Unexpected number of channels: {}", num_channels);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,20 +5,45 @@
|
|||||||
#include "ajm_aac.h"
|
#include "ajm_aac.h"
|
||||||
#include "ajm_result.h"
|
#include "ajm_result.h"
|
||||||
|
|
||||||
|
#include <aacdecoder_lib.h>
|
||||||
// using this internal header to manually configure the decoder in RAW mode
|
// using this internal header to manually configure the decoder in RAW mode
|
||||||
#include "externals/aacdec/fdk-aac/libAACdec/src/aacdecoder.h"
|
#include "externals/aacdec/fdk-aac/libAACdec/src/aacdecoder.h"
|
||||||
|
|
||||||
#include <aacdecoder_lib.h>
|
#include <algorithm> // std::transform
|
||||||
#include <magic_enum/magic_enum.hpp>
|
#include <iterator> // std::back_inserter
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace Libraries::Ajm {
|
namespace Libraries::Ajm {
|
||||||
|
|
||||||
|
std::span<const s16> AjmAacDecoder::GetOuputPcm(u32 skipped_pcm, u32 max_pcm) const {
|
||||||
|
const auto pcm_data = std::span(m_pcm_buffer).subspan(skipped_pcm);
|
||||||
|
return pcm_data.subspan(0, std::min<u32>(pcm_data.size(), max_pcm));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
size_t AjmAacDecoder::WriteOutputSamples<float>(SparseOutputBuffer& out, std::span<const s16> pcm) {
|
||||||
|
if (pcm.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_resample_buffer.clear();
|
||||||
|
constexpr float inv_scale = 1.0f / std::numeric_limits<s16>::max();
|
||||||
|
std::transform(pcm.begin(), pcm.end(), std::back_inserter(m_resample_buffer),
|
||||||
|
[](auto sample) { return float(sample) * inv_scale; });
|
||||||
|
|
||||||
|
return out.Write(std::span(m_resample_buffer));
|
||||||
|
}
|
||||||
|
|
||||||
AjmAacDecoder::AjmAacDecoder(AjmFormatEncoding format, AjmAacCodecFlags flags, u32 channels)
|
AjmAacDecoder::AjmAacDecoder(AjmFormatEncoding format, AjmAacCodecFlags flags, u32 channels)
|
||||||
: m_format(format), m_flags(flags), m_channels(channels), m_pcm_buffer(2048 * 8),
|
: m_format(format), m_flags(flags), m_channels(channels), m_pcm_buffer(1024 * 8),
|
||||||
m_skip_frames(True(flags & AjmAacCodecFlags::EnableNondelayOutput) ? 0 : 2) {}
|
m_skip_frames(True(flags & AjmAacCodecFlags::EnableNondelayOutput) ? 0 : 2) {
|
||||||
|
m_resample_buffer.reserve(m_pcm_buffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
AjmAacDecoder::~AjmAacDecoder() {
|
AjmAacDecoder::~AjmAacDecoder() {
|
||||||
aacDecoder_Close(m_decoder);
|
if (m_decoder) {
|
||||||
|
aacDecoder_Close(m_decoder);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TRANSPORT_TYPE TransportTypeFromConfigType(ConfigType config_type) {
|
TRANSPORT_TYPE TransportTypeFromConfigType(ConfigType config_type) {
|
||||||
@@ -98,7 +123,7 @@ AjmSidebandFormat AjmAacDecoder::GetFormat() const {
|
|||||||
.num_channels = static_cast<u32>(info->numChannels),
|
.num_channels = static_cast<u32>(info->numChannels),
|
||||||
.channel_mask = GetChannelMask(info->numChannels),
|
.channel_mask = GetChannelMask(info->numChannels),
|
||||||
.sampl_freq = static_cast<u32>(info->sampleRate),
|
.sampl_freq = static_cast<u32>(info->sampleRate),
|
||||||
.sample_encoding = m_format, // AjmFormatEncoding
|
.sample_encoding = m_format,
|
||||||
.bitrate = static_cast<u32>(info->bitRate),
|
.bitrate = static_cast<u32>(info->bitRate),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -130,8 +155,7 @@ DecoderResult AjmAacDecoder::ProcessData(std::span<u8>& input, SparseOutputBuffe
|
|||||||
const UINT sizes[] = {static_cast<UINT>(input.size())};
|
const UINT sizes[] = {static_cast<UINT>(input.size())};
|
||||||
UINT valid = sizes[0];
|
UINT valid = sizes[0];
|
||||||
aacDecoder_Fill(m_decoder, buffers, sizes, &valid);
|
aacDecoder_Fill(m_decoder, buffers, sizes, &valid);
|
||||||
auto ret = aacDecoder_DecodeFrame(m_decoder, reinterpret_cast<s16*>(m_pcm_buffer.data()),
|
auto ret = aacDecoder_DecodeFrame(m_decoder, m_pcm_buffer.data(), m_pcm_buffer.size(), 0);
|
||||||
m_pcm_buffer.size() / 2, 0);
|
|
||||||
|
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case AAC_DEC_OK:
|
case AAC_DEC_OK:
|
||||||
@@ -167,16 +191,16 @@ DecoderResult AjmAacDecoder::ProcessData(std::span<u8>& input, SparseOutputBuffe
|
|||||||
gapless.init.total_samples != 0 ? gapless.current.total_samples : info->aacSamplesPerFrame;
|
gapless.init.total_samples != 0 ? gapless.current.total_samples : info->aacSamplesPerFrame;
|
||||||
|
|
||||||
size_t pcm_written = 0;
|
size_t pcm_written = 0;
|
||||||
|
auto pcm = GetOuputPcm(skip_samples * info->numChannels, max_samples * info->numChannels);
|
||||||
switch (m_format) {
|
switch (m_format) {
|
||||||
case AjmFormatEncoding::S16:
|
case AjmFormatEncoding::S16:
|
||||||
pcm_written = WriteOutputSamples<s16>(output, skip_samples * info->numChannels,
|
pcm_written = output.Write(pcm);
|
||||||
max_samples * info->numChannels);
|
|
||||||
break;
|
break;
|
||||||
case AjmFormatEncoding::S32:
|
case AjmFormatEncoding::S32:
|
||||||
UNREACHABLE_MSG("NOT IMPLEMENTED");
|
UNREACHABLE_MSG("NOT IMPLEMENTED");
|
||||||
break;
|
break;
|
||||||
case AjmFormatEncoding::Float:
|
case AjmFormatEncoding::Float:
|
||||||
UNREACHABLE_MSG("NOT IMPLEMENTED");
|
pcm_written = WriteOutputSamples<float>(output, pcm);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
@@ -191,4 +215,4 @@ DecoderResult AjmAacDecoder::ProcessData(std::span<u8>& input, SparseOutputBuffe
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Ajm
|
} // namespace Libraries::Ajm
|
||||||
@@ -52,22 +52,18 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
size_t WriteOutputSamples(SparseOutputBuffer& output, u32 skipped_pcm, u32 max_pcm) {
|
size_t WriteOutputSamples(SparseOutputBuffer& output, std::span<const s16> pcm);
|
||||||
std::span<T> pcm_data{reinterpret_cast<T*>(m_pcm_buffer.data()),
|
std::span<const s16> GetOuputPcm(u32 skipped_pcm, u32 max_pcm) const;
|
||||||
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 AjmFormatEncoding m_format;
|
||||||
const AjmAacCodecFlags m_flags;
|
const AjmAacCodecFlags m_flags;
|
||||||
const u32 m_channels;
|
const u32 m_channels;
|
||||||
std::vector<u8> m_pcm_buffer;
|
std::vector<s16> m_pcm_buffer;
|
||||||
|
std::vector<float> m_resample_buffer;
|
||||||
|
|
||||||
u32 m_skip_frames = 0;
|
u32 m_skip_frames = 0;
|
||||||
InitializeParameters m_init_params = {};
|
InitializeParameters m_init_params = {};
|
||||||
AAC_DECODER_INSTANCE* m_decoder = nullptr;
|
AAC_DECODER_INSTANCE* m_decoder = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Libraries::Ajm
|
} // namespace Libraries::Ajm
|
||||||
@@ -532,6 +532,7 @@ void Emulator::LoadSystemModules(const std::string& game_serial) {
|
|||||||
{"libSceJson2.sprx", nullptr},
|
{"libSceJson2.sprx", nullptr},
|
||||||
{"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterLib},
|
{"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterLib},
|
||||||
{"libSceCesCs.sprx", nullptr},
|
{"libSceCesCs.sprx", nullptr},
|
||||||
|
{"libSceAudiodec.sprx", nullptr},
|
||||||
{"libSceFont.sprx", &Libraries::Font::RegisterlibSceFont},
|
{"libSceFont.sprx", &Libraries::Font::RegisterlibSceFont},
|
||||||
{"libSceFontFt.sprx", &Libraries::FontFt::RegisterlibSceFontFt},
|
{"libSceFontFt.sprx", &Libraries::FontFt::RegisterlibSceFontFt},
|
||||||
{"libSceFreeTypeOt.sprx", nullptr}});
|
{"libSceFreeTypeOt.sprx", nullptr}});
|
||||||
|
|||||||
Reference in New Issue
Block a user