From 4e0e3280d92442e39bb9aa1ec816f7af67e507a9 Mon Sep 17 00:00:00 2001 From: Martin Baliet Date: Sun, 5 May 2024 11:19:44 +0200 Subject: [PATCH 01/19] libScePosix| + sem_count --- CMakeLists.txt | 2 +- modules/libScePosix/entry.cpp | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e967360..db854bd9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.24) include(ExternalProject) -set(PSOFF_LIB_VERSION v.0.2) +set(PSOFF_LIB_VERSION v.0.3) set(PSOFF_RENDER_VERSION v.0.5-nightly_04.05.24) set(ProjectName psOff_${CMAKE_BUILD_TYPE}) diff --git a/modules/libScePosix/entry.cpp b/modules/libScePosix/entry.cpp index 289890c1..7e7ce18b 100644 --- a/modules/libScePosix/entry.cpp +++ b/modules/libScePosix/entry.cpp @@ -40,6 +40,14 @@ EXPORT SYSV_ABI int __NID(sem_post)(boost::interprocess::interprocess_semaphore* return Ok; } +EXPORT SYSV_ABI int __NID(sem_getvalue)(boost::interprocess::interprocess_semaphore** sem) { + if (sem == nullptr || *sem == nullptr) { + return POSIX_SET(ErrCode::_ESRCH); + } + return (*sem)->get_count(); + return Ok; +} + EXPORT SYSV_ABI int __NID(sem_reltimedwait_np)(boost::interprocess::interprocess_semaphore** sem, SceKernelTimespec* reltime) { auto now = boost::posix_time::microsec_clock::universal_time(); auto timeout = boost::posix_time::seconds(reltime->tv_sec) + boost::posix_time::microsec(reltime->tv_nsec / 1000); From 8de97550b8c02d55efebb991f39564107819c162 Mon Sep 17 00:00:00 2001 From: Martin Baliet Date: Sun, 5 May 2024 19:03:39 +0200 Subject: [PATCH 02/19] minor --- core/fileManager/fileManager.cpp | 8 ++++++-- modules/libSceAvPlayer/avplayer.cpp | 7 ++++++- modules/libSceAvPlayer/entry.cpp | 26 ++++++++++++++++++++++++++ modules/libScePlayGo/entry.cpp | 1 + 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/core/fileManager/fileManager.cpp b/core/fileManager/fileManager.cpp index 0aac6422..268ea213 100644 --- a/core/fileManager/fileManager.cpp +++ b/core/fileManager/fileManager.cpp @@ -220,6 +220,8 @@ class FileManager: public IFileManager { if ((*dir->m_file) == endDir) return 0; +#pragma pack(push, 1) + struct DataStruct { uint32_t fileno; uint16_t reclen; @@ -228,6 +230,8 @@ class FileManager: public IFileManager { char name[256]; }; +#pragma pack(pop, 1) + auto count = dir->count; int n = 0; @@ -237,7 +241,7 @@ class FileManager: public IFileManager { auto const filename = (*dir->m_file)->path().filename().string(); if (sizeof(DataStruct) + std::min(filename.size(), 255llu) >= nbytes) break; - item->fileno = 0; + item->fileno = count; item->type = ((*dir->m_file)->is_regular_file() ? 8 : 4); item->namlen = filename.copy(item->name, 255); item->name[item->namlen] = '\0'; @@ -245,7 +249,7 @@ class FileManager: public IFileManager { n += sizeof(DataStruct); item->reclen = sizeof(DataStruct); - LOG_DEBUG(L"KernelGetdirentries[%d]: %S %u offset:%u count:%u", handle, item->name, item->type, item->reclen, count); + LOG_DEBUG(L"KernelGetdirentries[%d]: %S %u offset:%u count:%u", handle, item->name, item->type, n, count); std::error_code err; (*dir->m_file).increment(err); diff --git a/modules/libSceAvPlayer/avplayer.cpp b/modules/libSceAvPlayer/avplayer.cpp index 7c803fd3..ccdd72db 100644 --- a/modules/libSceAvPlayer/avplayer.cpp +++ b/modules/libSceAvPlayer/avplayer.cpp @@ -279,7 +279,9 @@ bool Avplayer::getVideoData(void* info, bool isEx) { if (retRecv < 0) { if (retRecv == AVERROR(EAGAIN)) { if (!m_isStop) { + LOG_DEBUG(L"-> wait video frame"); m_video.m_cond.wait(lock); + LOG_DEBUG(L"<- wait video frame"); continue; } } else if (retRecv != AVERROR_EOF) { @@ -310,6 +312,7 @@ bool Avplayer::getVideoData(void* info, bool isEx) { auto const timestamp = (int64_t)(1000.0 * av_q2d(m_video.stream->time_base) * m_video.frame->best_effort_timestamp); // timestamp[seconds] to [ms] auto const curTime = (av_gettime() - m_startTime) / 1000; // [us] to [ms] + LOG_DEBUG(L"video frame timestamp:%lld", curTime); if (timestamp > curTime) { return false; } @@ -385,7 +388,9 @@ bool Avplayer::getAudioData(SceAvPlayerFrameInfo* info) { if (retRecv < 0) { if (retRecv == AVERROR(EAGAIN)) { if (!m_isStop) { + LOG_DEBUG(L"-> wait audio frame"); m_audio.m_cond.wait(lock); + LOG_DEBUG(L"<- wait audio frame"); continue; } } else if (retRecv != AVERROR_EOF) { @@ -522,7 +527,7 @@ std::unique_ptr Avplayer::threadFunc() { LOG_DEBUG(L"Queue Video Packet: numItems:%llu pts:%lld", m_video.decodeQueue.size(), packet->pts); } else if (packet->stream_index == m_audio.streamIndex) { m_audio.decodeQueue.push(packet); - LOG_DEBUG(L"Queue Video Packet: numItems:%llu pts:%lld", m_video.decodeQueue.size(), packet->pts); + LOG_DEBUG(L"Queue Audio Packet: numItems:%llu pts:%lld", m_audio.decodeQueue.size(), packet->pts); } else continue; } diff --git a/modules/libSceAvPlayer/entry.cpp b/modules/libSceAvPlayer/entry.cpp index eacbc2cb..94db122b 100644 --- a/modules/libSceAvPlayer/entry.cpp +++ b/modules/libSceAvPlayer/entry.cpp @@ -30,39 +30,57 @@ EXPORT SYSV_ABI int32_t sceAvPlayerAddSource(IAvplayer* avPlayer, const char* fi } EXPORT SYSV_ABI int32_t sceAvPlayerStreamCount(IAvplayer* avPlayer) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerGetStreamInfo(IAvplayer* avPlayer, uint32_t argStreamID, SceAvPlayerStreamInfo* argInfo) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerEnableStream(IAvplayer* avPlayer, uint32_t argStreamID) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerDisableStream(IAvplayer* avPlayer, uint32_t argStreamID) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerChangeStream(IAvplayer* avPlayer, uint32_t argOldStreamID, uint32_t argNewStreamID) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerStart(IAvplayer* avPlayer) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerStop(IAvplayer* avPlayer) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); avPlayer->stop(); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerPause(IAvplayer* avPlayer) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerResume(IAvplayer* avPlayer) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } @@ -85,18 +103,26 @@ EXPORT SYSV_ABI bool sceAvPlayerGetVideoData(IAvplayer* avPlayer, SceAvPlayerFra } EXPORT SYSV_ABI uint64_t sceAvPlayerCurrentTime(IAvplayer* avPlayer) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerJumpToTime(IAvplayer* avPlayer, uint64_t argJumpTimeMsec) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerSetTrickSpeed(IAvplayer* avPlayer, int32_t argTrickSpeed) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } EXPORT SYSV_ABI int32_t sceAvPlayerSetAvSyncMode(IAvplayer* avPlayer, SceAvPlayerAvSyncMode argSyncMode) { + LOG_USE_MODULE(libSceAvPlayer); + LOG_ERR(L"todo %S", __FUNCTION__); return Ok; } diff --git a/modules/libScePlayGo/entry.cpp b/modules/libScePlayGo/entry.cpp index 3736428e..ddb4a644 100644 --- a/modules/libScePlayGo/entry.cpp +++ b/modules/libScePlayGo/entry.cpp @@ -87,6 +87,7 @@ EXPORT SYSV_ABI int32_t scePlayGoSetInstallSpeed(ScePlayGoHandle handle, ScePlay EXPORT SYSV_ABI int32_t scePlayGoGetInstallSpeed(ScePlayGoHandle handle, ScePlayGoInstallSpeed* speed) { LOG_USE_MODULE(libScePlayGo); LOG_ERR(L"TODO: %S", __FUNCTION__); + *speed = 2; return Ok; } From 9f360f34265727b09d4c0d346cef4cee1d4f7548 Mon Sep 17 00:00:00 2001 From: Martin Baliet Date: Sun, 5 May 2024 20:13:22 +0200 Subject: [PATCH 03/19] avplayer| getlast timestamp --- modules/libSceAvPlayer/avplayer.cpp | 8 +++++++- modules/libSceAvPlayer/avplayer.h | 7 +++++++ modules/libSceAvPlayer/entry.cpp | 4 +--- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/modules/libSceAvPlayer/avplayer.cpp b/modules/libSceAvPlayer/avplayer.cpp index ccdd72db..a5dae8b2 100644 --- a/modules/libSceAvPlayer/avplayer.cpp +++ b/modules/libSceAvPlayer/avplayer.cpp @@ -79,7 +79,8 @@ class Avplayer: public IAvplayer { std::array m_videoStride; std::array m_videoPlane; - int64_t m_startTime = 0; + int64_t m_startTime = 0; + uint64_t m_latestTimestamp = 0; // Avplayer Data AVFormatContext* m_pFmtCtx = nullptr; @@ -172,6 +173,8 @@ class Avplayer: public IAvplayer { return m_isVideoActive || m_isAudioActive; } + uint64_t getCurrentTime() const final { return m_latestTimestamp; } + void stop() final { LOG_USE_MODULE(AvPlayer); LOG_DEBUG(L"stop"); @@ -317,6 +320,8 @@ bool Avplayer::getVideoData(void* info, bool isEx) { return false; } + m_latestTimestamp = timestamp; + LOG_DEBUG(L"Received video frame, timestamp:%lld", m_video.frame->pts); m_video.getNewFrame = true; @@ -415,6 +420,7 @@ bool Avplayer::getAudioData(SceAvPlayerFrameInfo* info) { } auto const timestamp = (int64_t)(1000.0 * av_q2d(m_audio.stream->time_base) * m_audio.frame->best_effort_timestamp); // timestamp[seconds] to [ms] + m_latestTimestamp = timestamp; // Convert and copy int const outNumSamples = swr_get_out_samples(m_swrCtx, m_audio.frame->nb_samples); diff --git a/modules/libSceAvPlayer/avplayer.h b/modules/libSceAvPlayer/avplayer.h index 93f7f941..3fb84d57 100644 --- a/modules/libSceAvPlayer/avplayer.h +++ b/modules/libSceAvPlayer/avplayer.h @@ -20,6 +20,13 @@ class IAvplayer { virtual bool isPlaying() = 0; virtual void stop() = 0; + /** + * @brief Get the latest timestamp + * + * @return uint64_t [ms] + */ + virtual uint64_t getCurrentTime() const = 0; + virtual ~IAvplayer() = default; }; diff --git a/modules/libSceAvPlayer/entry.cpp b/modules/libSceAvPlayer/entry.cpp index 94db122b..3dbda38f 100644 --- a/modules/libSceAvPlayer/entry.cpp +++ b/modules/libSceAvPlayer/entry.cpp @@ -103,9 +103,7 @@ EXPORT SYSV_ABI bool sceAvPlayerGetVideoData(IAvplayer* avPlayer, SceAvPlayerFra } EXPORT SYSV_ABI uint64_t sceAvPlayerCurrentTime(IAvplayer* avPlayer) { - LOG_USE_MODULE(libSceAvPlayer); - LOG_ERR(L"todo %S", __FUNCTION__); - return Ok; + return avPlayer->getCurrentTime(); } EXPORT SYSV_ABI int32_t sceAvPlayerJumpToTime(IAvplayer* avPlayer, uint64_t argJumpTimeMsec) { From 8f666c12f831c98831b63fb3e7ec220d48bef18c Mon Sep 17 00:00:00 2001 From: Martin Baliet Date: Mon, 6 May 2024 17:12:59 +0200 Subject: [PATCH 04/19] libSceNgs2| dump state --- modules/libSceNgs2/CMakeLists.txt | 8 +- modules/libSceNgs2/codes.h | 10 +- modules/libSceNgs2/entry.cpp | 706 ++++++++++++++++-------------- modules/libSceNgs2/readFuncs.cpp | 160 +++++++ modules/libSceNgs2/readFuncs.h | 26 ++ modules/libSceNgs2/reader.cpp | 127 ++++++ modules/libSceNgs2/reader.h | 14 + modules/libSceNgs2/temp.txt | 34 ++ modules/libSceNgs2/types.h | 180 ++++++-- 9 files changed, 891 insertions(+), 374 deletions(-) create mode 100644 modules/libSceNgs2/readFuncs.cpp create mode 100644 modules/libSceNgs2/readFuncs.h create mode 100644 modules/libSceNgs2/reader.cpp create mode 100644 modules/libSceNgs2/reader.h create mode 100644 modules/libSceNgs2/temp.txt diff --git a/modules/libSceNgs2/CMakeLists.txt b/modules/libSceNgs2/CMakeLists.txt index eb7fae9f..7aa4c0bb 100644 --- a/modules/libSceNgs2/CMakeLists.txt +++ b/modules/libSceNgs2/CMakeLists.txt @@ -1,10 +1,14 @@ cmake_minimum_required(VERSION 3.24) include(../setupModule.cmake) +add_compile_definitions( + BOOST_ALL_NO_LIB +) + set(libName libSceNgs2) project(${libName}) -add_library(${libName} SHARED entry.cpp) +add_library(${libName} SHARED entry.cpp readFuncs.cpp reader.cpp) set(FFMPEG_LIBS avformat @@ -15,6 +19,6 @@ set(FFMPEG_LIBS ) add_dependencies(${libName} core) -target_link_libraries(${libName} PRIVATE core.lib ${FFMPEG_LIBS}) +target_link_libraries(${libName} PRIVATE core.lib ${FFMPEG_LIBS} libboost_thread libboost_chrono) setupModule(${libName}) diff --git a/modules/libSceNgs2/codes.h b/modules/libSceNgs2/codes.h index 564bb031..045f4900 100644 --- a/modules/libSceNgs2/codes.h +++ b/modules/libSceNgs2/codes.h @@ -7,6 +7,7 @@ constexpr int32_t INVALID_WAVEFORM_DATA = -2142632952; constexpr int32_t INVALID_BUFFER_ADDRESS = -2142633465; constexpr int32_t INVALID_BUFFER_SIZE = -2142633466; constexpr int32_t INVALID_SYSTEM_HANDLE = -2142633424; +constexpr int32_t INVALID_VOICE_HANDLE = -2142633216; constexpr int32_t INVALID_RACK_HANDLE = -2142633375; constexpr int32_t INVALID_VOICE_INDEX = -2142633214; constexpr int32_t INVALID_BUFFER_ALLOCATOR = -2142633462; @@ -25,4 +26,11 @@ constexpr int32_t SCE_NGS2_MAX_MATRIX_LEVELS = 64; constexpr int32_t SCE_NGS2_RACK_NAME_LENGTH = 16; constexpr int32_t SCE_NGS2_SYSTEM_NAME_LENGTH = 16; -constexpr int32_t SCE_NGS2_SAMPLER_VOICE_ADD_WAVEFORM_BLOCKS = 0x10000001; +constexpr uint16_t SCE_NGS2_RACK_ID_VOICE = 0x0000; +constexpr uint16_t SCE_NGS2_RACK_ID_SAMPLER = 0x1000; +constexpr uint16_t SCE_NGS2_RACK_ID_SUBMIXER = 0x2000; +constexpr uint16_t SCE_NGS2_RACK_ID_MASTERING = 0x3000; + +constexpr uint16_t SCE_NGS2_RACK_ID_CUSTOM_SAMPLER = 0x4001; +constexpr uint16_t SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER = 0x4002; +constexpr uint16_t SCE_NGS2_RACK_ID_CUSTOM_MASTERING = 0x4003; \ No newline at end of file diff --git a/modules/libSceNgs2/entry.cpp b/modules/libSceNgs2/entry.cpp index f83b4525..f0d789c3 100644 --- a/modules/libSceNgs2/entry.cpp +++ b/modules/libSceNgs2/entry.cpp @@ -1,177 +1,285 @@ -#include "codes.h" -#include "common.h" extern "C" { -#include "libavformat/avformat.h" +#include +#include +#include } +#include "core/fileManager/ifile.h" #include "core/kernel/filesystem.h" #include "core/kernel/pthread.h" #include "logging.h" +#include "readFuncs.h" +#include "reader.h" #include "types.h" +#include + LOG_DEFINE_MODULE(libSceNgs2); namespace { -enum WaveformInfoType { - WAVEFORM_FILE, - WAVEFORM_DATA, - WAVEFORM_USER, -}; +static boost::mutex MUTEX_INT; -struct WaveformInfo { - WaveformInfoType type; - char pad[4]; +int32_t _voiceControlWaveformBlock(SceNgs2Handle* voh, const SceNgs2SamplerVoiceWaveformBlocksParam* svwfbp) { + LOG_USE_MODULE(libSceNgs2); - union WaveformPtr { - int fileHandle; - SceWaveformUserFunc* userFunc; - const void* dataPtr; - } ud; + LOG_TRACE(L"waveblock: %d\n", svwfbp->numBlocks); + LOG_TRACE(L"waveptr: %llx\n", svwfbp->data); - size_t size; - long offset; -}; + if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; + auto voice = (SceNgs2Handle_voice*)voh; -static SceNgs2ChannelsCount ParseChanCount(int num) { - LOG_USE_MODULE(libSceNgs2); + voice->reader = std::make_unique().release(); + voice->reader->init(svwfbp->data, svwfbp->aBlock[0].size); - switch (num) { - case 1: return SceNgs2ChannelsCount::CH_1_0; + return Ok; +} + +int32_t voiceControl_voice(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + switch ((SceNgs2VoiceParam)(phead->id & 0xFFFF)) { + case SceNgs2VoiceParam::SET_MATRIX_LEVELS: { + } break; + case SceNgs2VoiceParam::SET_PORT_VOLUME: { + } break; + case SceNgs2VoiceParam::SET_PORT_MATRIX: { + } break; + case SceNgs2VoiceParam::SET_PORT_DELAY: { + } break; + case SceNgs2VoiceParam::PATCH: { + } break; + case SceNgs2VoiceParam::KICK_EVENT: { + } break; + case SceNgs2VoiceParam::SET_CALLBACK: { + } break; + } + return Ok; +} - case 2: return SceNgs2ChannelsCount::CH_2_0; +int32_t voiceControl_mastering(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + switch ((SceNgs2MasteringParam)(phead->id & 0xFFFF)) { + case SceNgs2MasteringParam::SETUP: { + } break; + case SceNgs2MasteringParam::SET_MATRIX: { + } break; + case SceNgs2MasteringParam::SET_LFE: { + } break; + case SceNgs2MasteringParam::SET_LIMITER: { + } break; + case SceNgs2MasteringParam::SET_GAIN: { + } break; + case SceNgs2MasteringParam::SET_OUTPUT: { + } break; + case SceNgs2MasteringParam::SET_PEAK_METER: { + } break; + } + return Ok; +} - case 6: return SceNgs2ChannelsCount::CH_5_1; +int32_t voiceControl_sampler(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + switch ((SceNgs2SamplerParam)(phead->id & 0xFFFF)) { + case SceNgs2SamplerParam::SETUP: { + } break; + case SceNgs2SamplerParam::ADD_WAVEFORM_BLOCKS: { + return _voiceControlWaveformBlock(voh, (const SceNgs2SamplerVoiceWaveformBlocksParam*)phead); + } break; + case SceNgs2SamplerParam::REPLACE_WAVEFORM_ADDRESS: { + } break; + case SceNgs2SamplerParam::SET_WAVEFORM_FRAME_OFFSET: { + } break; + case SceNgs2SamplerParam::EXIT_LOOP: { + } break; + case SceNgs2SamplerParam::SET_PITCH: { + } break; + case SceNgs2SamplerParam::SET_ENVELOPE: { + } break; + case SceNgs2SamplerParam::SET_DISTORTION: { + } break; + case SceNgs2SamplerParam::SET_USER_FX: { + } break; + case SceNgs2SamplerParam::SET_PEAK_METER: { + } break; + case SceNgs2SamplerParam::SET_FILTER: { + } break; + } + return Ok; +} - case 8: return SceNgs2ChannelsCount::CH_7_1; +int32_t voiceControl_submixer(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + switch ((SceNgs2SubmixerParam)(phead->id & 0xFFFF)) { + case SceNgs2SubmixerParam::SETUP: { + } break; + case SceNgs2SubmixerParam::SET_ENVELOPE: { + } break; + case SceNgs2SubmixerParam::SET_COMPRESSOR: { + } break; + case SceNgs2SubmixerParam::SET_DISTORTION: { + } break; + case SceNgs2SubmixerParam::SET_USER_FX: { + } break; + case SceNgs2SubmixerParam::SET_PEAK_METER: { + } break; + case SceNgs2SubmixerParam::SET_FILTER: { + } break; } + return Ok; +} +} // namespace - LOG_CRIT(L"Invalid channels count sent to ParseChanCount!"); - return SceNgs2ChannelsCount::INVALID; +SceNgs2Handle_voice::~SceNgs2Handle_voice() { + if (reader != nullptr) delete reader; } -static SceNgs2WaveFormType ParseWaveType(AVCodecID codec) { - switch (codec) { - case AVCodecID::AV_CODEC_ID_PCM_S8: return SceNgs2WaveFormType::PCM_I8; +extern "C" { - case AVCodecID::AV_CODEC_ID_PCM_U8: return SceNgs2WaveFormType::PCM_U8; +EXPORT const char* MODULE_NAME = "libSceNgs2"; - case AVCodecID::AV_CODEC_ID_ATRAC9: return SceNgs2WaveFormType::ATRAC9; +// ### Create +EXPORT SYSV_ABI int32_t sceNgs2RackQueryBufferSize(uint32_t rackId, const SceNgs2RackOption* ro, SceNgs2ContextBufferInfo* cbi) { + if (cbi == nullptr) return Err::Ngs2::INVALID_BUFFER_ADDRESS; + if (ro != nullptr && ro->size < sizeof(SceNgs2RackOption)) return Err::Ngs2::INVALID_OPTION_SIZE; - default: return SceNgs2WaveFormType::NONE; - } + auto const numVoices = ro != nullptr ? ro->maxVoices : SceNgs2RackOption().maxVoices; + cbi->hostBufferSize = sizeof(SceNgs2Handle_rack) + (numVoices * sizeof(SceNgs2Handle_voice)); + return Ok; +} + +EXPORT SYSV_ABI int32_t sceNgs2SystemQueryBufferSize(const SceNgs2SystemOption* sysopt, SceNgs2ContextBufferInfo* cbi) { + if (cbi == nullptr) return Err::Ngs2::INVALID_BUFFER_ADDRESS; + cbi->hostBufferSize = sizeof(SceNgs2Handle_system); + return Ok; } -struct RIFFBuf { - const uint8_t* data; - size_t size; - uint64_t offset; -}; +EXPORT SYSV_ABI int32_t sceNgs2SystemCreateWithAllocator(const SceNgs2SystemOption* sysopt, SceNgs2BufferAllocator* alloc, SceNgs2Handle** outh) { + LOG_USE_MODULE(libSceNgs2); + + boost::unique_lock lock(MUTEX_INT); + + if (alloc == nullptr || alloc->allocHandler == nullptr) return Err::Ngs2::INVALID_BUFFER_ALLOCATOR; + if (outh == nullptr) return Err::Ngs2::INVALID_OUT_ADDRESS; + if (sysopt != nullptr && sysopt->size < sizeof(SceNgs2SystemOption)) return Err::Ngs2::INVALID_OPTION_SIZE; + + SceNgs2ContextBufferInfo cbi = { + .hostBuffer = nullptr, + .hostBufferSize = sizeof(SceNgs2Handle_system), + .userData = alloc->userData, + }; + + if (auto ret = alloc->allocHandler(&cbi)) { + LOG_ERR(L"Ngs2System: Allocation failed!"); + return ret; + } + + *outh = new (cbi.hostBuffer) SceNgs2Handle_system(alloc); -static int readbuf(void* op, uint8_t* buf, int bufsz) { - auto rb = (RIFFBuf*)op; - if (rb->offset > rb->size) return AVERROR_EOF; - int read = std::min(int(rb->size - rb->offset), bufsz); - if (read == 0) return AVERROR_EOF; - ::memcpy(buf, rb->data + rb->offset, read); - return read; + return Ok; } -static int64_t seekbuf(void* op, int64_t offset, int whence) { - auto rb = (RIFFBuf*)op; - if (whence == AVSEEK_SIZE) return rb->size; +EXPORT SYSV_ABI int32_t sceNgs2SystemCreate(const SceNgs2SystemOption* sysopt, const SceNgs2ContextBufferInfo* cbi, SceNgs2Handle** outh) { + LOG_USE_MODULE(libSceNgs2); + boost::unique_lock lock(MUTEX_INT); + + if (outh == nullptr) return Err::Ngs2::INVALID_OUT_ADDRESS; + if (sysopt != nullptr && sysopt->size < sizeof(SceNgs2SystemOption)) return Err::Ngs2::INVALID_OPTION_SIZE; + if (cbi == nullptr || cbi->hostBuffer == nullptr || cbi->hostBufferSize < sizeof(SceNgs2Handle)) return Err::Ngs2::INVALID_BUFFER_ADDRESS; - if (rb->data == nullptr || rb->size == 0) return -1; - if (whence == SEEK_SET) - rb->offset = offset; - else if (whence == SEEK_CUR) - rb->offset += offset; - else if (whence == SEEK_END) - rb->offset = rb->size - offset; + *outh = new (cbi->hostBuffer) SceNgs2Handle_system(nullptr); - return offset; + return (*outh) != nullptr ? Ok : Err::Ngs2::FAIL; } -static int32_t ParseData(const uint8_t* data, size_t size, SceNgs2WaveformFormat* wf) { +EXPORT SYSV_ABI int32_t sceNgs2RackCreate(SceNgs2Handle* sysh, uint32_t rackId, const SceNgs2RackOption* ropt, const SceNgs2ContextBufferInfo* cbi, + SceNgs2Handle** outh) { LOG_USE_MODULE(libSceNgs2); - AVFormatContext* fmtctx = avformat_alloc_context(); + boost::unique_lock lock(MUTEX_INT); - auto aBufferIo = (uint8_t*)av_malloc(4096 + AV_INPUT_BUFFER_PADDING_SIZE); + if (outh == nullptr) return Err::Ngs2::INVALID_OUT_ADDRESS; + if (sysh == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; + if (ropt != nullptr && ropt->size < sizeof(SceNgs2RackOption)) return Err::Ngs2::INVALID_OPTION_SIZE; + if (cbi == nullptr || cbi->hostBuffer == nullptr || cbi->hostBufferSize < sizeof(SceNgs2Handle)) return Err::Ngs2::INVALID_BUFFER_ADDRESS; + auto system = (SceNgs2Handle_system*)sysh; - RIFFBuf rb { - .data = data, - .size = size, - .offset = 0, - }; + *outh = new (cbi->hostBuffer) SceNgs2Handle_rack(system, ropt, rackId); - AVIOContext* avioctx = avio_alloc_context(aBufferIo, 4096, 0, &rb, &readbuf, nullptr, &seekbuf); - fmtctx->pb = avioctx; - fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; + auto rack = (SceNgs2Handle_rack*)(*outh); - int ret = avformat_open_input(&fmtctx, "nullptr", nullptr, nullptr); - if (ret != 0) { - LOG_ERR(L"ParseRIFF: ffmpeg failed to read passed data: %d", ret); - return Err::Ngs2::FAIL; - } + // Init voices + { + auto addrVoices = (uint64_t)rack + sizeof(SceNgs2Handle_rack); // At end of rack struct + + rack->voices = (SceNgs2Handle_voice*)addrVoices; - AVStream* astream = nullptr; - for (int i = 0; fmtctx->nb_streams; i++) { - if (fmtctx->streams[i]->codecpar->codec_type == AVMediaType::AVMEDIA_TYPE_AUDIO) { - astream = fmtctx->streams[i]; - break; + for (uint16_t n = 0; n < rack->options.maxVoices; ++n, addrVoices += sizeof(SceNgs2Handle_voice)) { + auto pVoice = new ((void*)addrVoices) SceNgs2Handle_voice(rack); } } - - if (astream == nullptr) { - LOG_ERR(L"ParseRIFF: no audio stream detected!"); + // - + + // Add to system + if (rackId == SCE_NGS2_RACK_ID_MASTERING || rackId == SCE_NGS2_RACK_ID_CUSTOM_MASTERING) { + system->mastering = rack; + } else if (rackId == SCE_NGS2_RACK_ID_SAMPLER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SAMPLER) { + system->sampler = rack; + } else if (rackId == SCE_NGS2_RACK_ID_SUBMIXER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER) { + system->submixer = rack; + } else { + LOG_ERR(L"-> Rack: undefined rackid %u", rackId); return Err::Ngs2::FAIL; } - wf->info.type = ParseWaveType(astream->codecpar->codec_id); - wf->info.sampleRate = astream->codecpar->sample_rate; - wf->info.channelsCount = ParseChanCount(astream->codecpar->ch_layout.nb_channels); + return (*outh) != nullptr ? Ok : Err::Ngs2::FAIL; +} - // These are unknown for now - wf->loopBeginPos = wf->loopEndPos = 0; - wf->samplesCount = 0; - wf->offset = 0; - wf->size = 0; +EXPORT SYSV_ABI int32_t sceNgs2RackCreateWithAllocator(SceNgs2Handle* sysh, uint32_t rackId, const SceNgs2RackOption* ro, const SceNgs2BufferAllocator* alloc, + SceNgs2Handle** outh) { + if (sysh == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; + if (alloc == nullptr) return Err::Ngs2::INVALID_BUFFER_ALLOCATOR; + LOG_USE_MODULE(libSceNgs2); + boost::unique_lock lock(MUTEX_INT); - // std::vector* frames = new std::vector; + auto system = (SceNgs2Handle_system*)sysh; - // AVPacket packet; - // while (av_read_frame(fmtctx, &packet) >= 0) { - // if (packet.stream_index == astream->index) { - // frames->insert(frames->end(), packet); - // } - // // av_packet_unref(&packet); - // } + auto const numVoices = ro != nullptr ? ro->maxVoices : SceNgs2RackOption().maxVoices; - wf->numBlocks = 0; - wf->block[0].userData = 0; - // wf->block[0].userData = (uintptr_t)frames; + SceNgs2ContextBufferInfo cbi = { + .hostBuffer = nullptr, + .hostBufferSize = sizeof(SceNgs2Handle_rack) + (numVoices * sizeof(SceNgs2Handle_voice)), + .userData = alloc->userData, + }; - av_free(avioctx); - avformat_close_input(&fmtctx); + if (auto ret = alloc->allocHandler(&cbi)) { + LOG_ERR(L"Ngs2Rack: Allocation failed!"); + return ret; + } - return Ok; -} + *outh = new (cbi.hostBuffer) SceNgs2Handle_rack(system, ro, rackId); -static int32_t ProcessWaveData(WaveformInfo* wi, SceNgs2WaveformFormat* wf) { - LOG_USE_MODULE(libSceNgs2); + auto rack = (SceNgs2Handle_rack*)(*outh); + // Init voices + { + auto addrVoices = (uint64_t)rack + sizeof(SceNgs2Handle_rack); // At end of rack struct - switch (wi->type) { - case WAVEFORM_DATA: return ParseData((const uint8_t*)wi->ud.dataPtr, wi->size, wf); + rack->voices = (SceNgs2Handle_voice*)addrVoices; - default: LOG_ERR(L"Unimplemented waveform reader: %d", wi->type); + for (uint16_t n = 0; n < rack->options.maxVoices; ++n, addrVoices += sizeof(SceNgs2Handle_voice)) { + auto pVoice = new ((void*)addrVoices) SceNgs2Handle_voice(rack); + } + } + // - + + // Add to system + if (rackId == SCE_NGS2_RACK_ID_MASTERING || rackId == SCE_NGS2_RACK_ID_CUSTOM_MASTERING) { + system->mastering = rack; + } else if (rackId == SCE_NGS2_RACK_ID_SAMPLER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SAMPLER) { + system->sampler = rack; + } else if (rackId == SCE_NGS2_RACK_ID_SUBMIXER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER) { + system->submixer = rack; + } else { + LOG_ERR(L"-> Rack: undefined rackid %u", rackId); + return Err::Ngs2::FAIL; } - /* todo: Deal with WAV/VAG files */ - return Err::Ngs2::INVALID_WAVEFORM_DATA; + return (*outh) != nullptr ? Ok : Err::Ngs2::FAIL; } -} // namespace - -extern "C" { -EXPORT const char* MODULE_NAME = "libSceNgs2"; +// --- create EXPORT SYSV_ABI int32_t sceNgs2ReportRegisterHandler(uint32_t type, SceNgs2ReportHandler func, uintptr_t userData, SceNgs2Handle** outh) { LOG_USE_MODULE(libSceNgs2); @@ -197,30 +305,85 @@ EXPORT SYSV_ABI int32_t sceNgs2CustomRackGetModuleInfo(SceNgs2Handle* rh, uint32 return Ok; } -EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformData(const void* ptr, size_t size, SceNgs2WaveformFormat* wf) { - LOG_USE_MODULE(libSceNgs2); - LOG_TRACE(L"todo %S", __FUNCTION__); +// ### WAVE File parsing +/** + * @brief Parse the wave (file) data + * + * @param ptr Game/Application reads (file) and exposes the data pointer + * @param size size of data(file) + * @param wf + * @return result + */ +EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformData(const void* ptr, size_t size, SceNgs2WaveformFormat* wf) { if (ptr == nullptr) { return Err::Ngs2::INVALID_BUFFER_ADDRESS; } + boost::unique_lock lock(MUTEX_INT); + + userData_inerBuffer userData {ptr, size, 0}; + return parseWave(readFunc_linearBuffer, seekFunc_linearBuffer, &userData, wf); +} + +/** + * @brief Parse the wave file + * + * @param ptr Game/Application reads file and exposes the data pointer + * @param offset offset of file + * @param wf + * @return result + */ + +EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformFile(const char* path, long offset, SceNgs2WaveformFormat* wf) { + boost::unique_lock lock(MUTEX_INT); - WaveformInfo wi { - .type = WAVEFORM_DATA, - .ud = {.dataPtr = ptr}, - .size = size, + filesystem::SceOpen const fileFlags { + .mode = filesystem::SceOpenMode::RDONLY, }; - return ProcessWaveData(&wi, wf); + auto fileHandle = filesystem::open(path, fileFlags, 0); + if (fileHandle < 0) return Err::Ngs2::INVALID_WAVEFORM_DATA; + + if (offset != 0) filesystem::lseek(fileHandle, offset, (int)SceWhence::beg); + return parseWave(readFunc_file, seekFunc_file, reinterpret_cast(fileHandle), wf); +} + +/** + * @brief Parse the wave file using the provided function + * + * @param func Game/Application reads file and exposes the data pointer + * @param userData_ offset of file + * @param wf + * @return result + */ + +EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformUser(SceWaveformUserFunc func, uintptr_t userData_, SceNgs2WaveformFormat* wf) { + LOG_USE_MODULE(libSceNgs2); + LOG_ERR(L"todo %S", __FUNCTION__); + // todo parseWave uses seek for totalsize + return Err::Ngs2::FAIL; + + // if (func == nullptr) { + // return Err::Ngs2::INVALID_BUFFER_ADDRESS; + // } + // boost::unique_lock lock(MUTEX_INT); + + // userData_user userData {func, userData_, 0}; + // return parseWave(readFunc_user, seekFunc_user, (void*)&userData, wf); } +// - wave parsing + EXPORT SYSV_ABI int32_t sceNgs2GetWaveformFrameInfo(const SceNgs2WaveformInfo* fmt, uint32_t* outFrameSize, uint32_t* outNumFrameSamples, uint32_t* outUnitsPerFrame, uint32_t* outNumDelaySamples) { LOG_USE_MODULE(libSceNgs2); LOG_TRACE(L"todo %S", __FUNCTION__); + + boost::unique_lock lock(MUTEX_INT); + if (outFrameSize) *outFrameSize = 1; // Some games crashes with divide by zero exception if we set 0 here - if (outNumFrameSamples) *outNumFrameSamples = 0; - if (outUnitsPerFrame) *outUnitsPerFrame = 0; + if (outNumFrameSamples) *outNumFrameSamples = 1; + if (outUnitsPerFrame) *outUnitsPerFrame = 1; if (outNumDelaySamples) *outNumDelaySamples = 0; return Ok; } @@ -238,44 +401,6 @@ EXPORT SYSV_ABI int32_t sceNgs2PanInit() { return Ok; } -EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformFile(const char* path, long offset, SceNgs2WaveformFormat* wf) { - LOG_USE_MODULE(libSceNgs2); - LOG_ERR(L"todo %S", __FUNCTION__); - - filesystem::SceOpen flags { - .mode = filesystem::SceOpenMode::RDONLY, - }; - - WaveformInfo wi { - .type = WAVEFORM_DATA, - .ud = {.fileHandle = filesystem::open(path, flags, {})}, - .offset = offset, - }; - - if (wi.ud.fileHandle == 0) { - return Err::Ngs2::INVALID_WAVEFORM_DATA; - } - - return ProcessWaveData(&wi, wf); -} - -EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformUser(SceWaveformUserFunc* user, size_t size, SceNgs2WaveformFormat* wf) { - LOG_USE_MODULE(libSceNgs2); - LOG_ERR(L"todo %S", __FUNCTION__); - - if (user == nullptr) { - return Err::Ngs2::INVALID_BUFFER_ADDRESS; - } - - WaveformInfo wi { - .type = WAVEFORM_USER, - .ud = {.userFunc = user}, - .size = size, - }; - - return ProcessWaveData(&wi, wf); -} - EXPORT SYSV_ABI int32_t sceNgs2RackGetInfo(SceNgs2Handle* rh, SceNgs2RackInfo* outi, size_t infosz) { LOG_USE_MODULE(libSceNgs2); LOG_ERR(L"todo %S", __FUNCTION__); @@ -296,12 +421,16 @@ EXPORT SYSV_ABI int32_t sceNgs2RackGetUserData(SceNgs2Handle* rh, uintptr_t* use } EXPORT SYSV_ABI int32_t sceNgs2RackGetVoiceHandle(SceNgs2Handle* rh, uint32_t voiceId, SceNgs2Handle** outh) { - if (rh == nullptr) return Err::Ngs2::INVALID_RACK_HANDLE; - if (voiceId > rh->un.rack.info.maxVoices) return Err::Ngs2::INVALID_VOICE_INDEX; LOG_USE_MODULE(libSceNgs2); - LOG_TRACE(L"todo %S", __FUNCTION__); - // todo: write to outh voice handle from rack - *outh = &rh->un.rack.voices[voiceId]; + boost::unique_lock lock(MUTEX_INT); + + if (rh == nullptr || rh->type != SceNgs2HandleType::Rack) return Err::Ngs2::INVALID_RACK_HANDLE; + + auto rack = (SceNgs2Handle_rack*)rh; + if (voiceId > rack->options.maxVoices) return Err::Ngs2::INVALID_VOICE_INDEX; + + *outh = (SceNgs2Handle*)((uint64_t)rack->voices + voiceId * sizeof(SceNgs2Handle_voice)); + return Ok; } @@ -361,20 +490,35 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemUnlock(SceNgs2Handle* sysh) { EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBufferInfo* rbi, int32_t count) { LOG_USE_MODULE(libSceNgs2); LOG_TRACE(L"todo %S", __FUNCTION__); - if (sysh == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; + boost::unique_lock lock(MUTEX_INT); + + // if (sysh == nullptr || sysh->un.rack.voices == nullptr || sysh->un.rack.voices->un.voice.reader == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; if (rbi->bufferPtr == nullptr) return Err::Ngs2::INVALID_BUFFER_ADDRESS; if (rbi->bufferSize == 0) return Err::Ngs2::INVALID_BUFFER_SIZE; if (rbi->waveType >= SceNgs2WaveFormType::MAX_TYPES) return Err::Ngs2::INVALID_WAVEFORM_TYPE; if (rbi->channelsCount > SceNgs2ChannelsCount::CH_7_1) return Err::Ngs2::INVALID_NUM_CHANNELS; - for (int32_t i = 0; i < count; i++) { - if (rbi[i].bufferPtr != nullptr) { - std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); - } - } + auto system = (SceNgs2Handle_system*)sysh; - // todo: ffmpeg should convert all the wave data to `rbi->waveType` + if (system->sampler == nullptr) { + for (int32_t i = 0; i < count; i++) { + if (rbi[i].bufferPtr != nullptr) { + std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); + } + } + } else { + for (int32_t i = 0; i < count; i++) { + if (rbi[i].bufferPtr != nullptr) { + auto reader = system->sampler->voices[0].reader; + if (reader != nullptr) { + reader->getAudio(rbi[i].bufferPtr, rbi[i].bufferSize); + } else { + std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); + } + } + } + } return Ok; } @@ -408,36 +552,39 @@ EXPORT SYSV_ABI int32_t sceNgs2VoiceGetPortInfo(SceNgs2Handle** vh, uint32_t por return Ok; } -static int32_t _voiceControlWaveformBlock(SceNgs2Handle* voh, const SceNgs2SamplerVoiceWaveformBlocksParam* svwfbp) { - LOG_USE_MODULE(libSceNgs2); - LOG_TRACE(L"waveblock: %d\n", svwfbp->numBlocks); - if (svwfbp->aBlock) LOG_TRACE(L"waveptr: %llx\n", svwfbp->aBlock[0].userData); - return Ok; -} - EXPORT SYSV_ABI int32_t sceNgs2VoiceControl(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { LOG_USE_MODULE(libSceNgs2); - LOG_TRACE(L"todo %S", __FUNCTION__); - switch (phead->id) { - case SCE_NGS2_SAMPLER_VOICE_ADD_WAVEFORM_BLOCKS: return _voiceControlWaveformBlock(voh, (const SceNgs2SamplerVoiceWaveformBlocksParam*)phead); + boost::unique_lock lock(MUTEX_INT); - case (uint32_t)SceNgs2VoiceParam::SET_PORT_VOLUME: break; + uint16_t const rackId = phead->id >> 16; - default: LOG_TRACE(L"Unhandled voice control command: (%p, %08x)", voh, phead->id); - } + printf("0x%u 0x%u\n", rackId, (uint16_t)(phead->id & 0xffff)); // todo racecondition somewhere + if (rackId == SCE_NGS2_RACK_ID_VOICE) return voiceControl_voice(voh, phead); + if (rackId == SCE_NGS2_RACK_ID_MASTERING || rackId == SCE_NGS2_RACK_ID_CUSTOM_MASTERING) return voiceControl_mastering(voh, phead); + if (rackId == SCE_NGS2_RACK_ID_SAMPLER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SAMPLER) return voiceControl_sampler(voh, phead); + if (rackId == SCE_NGS2_RACK_ID_SUBMIXER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER) return voiceControl_submixer(voh, phead); + + LOG_ERR(L"Unhandled rackId: %08x", rackId); return Ok; } EXPORT SYSV_ABI int32_t sceNgs2VoiceGetState(SceNgs2Handle* voh, SceNgs2VoiceState* state, size_t size) { - LOG_USE_MODULE(libSceNgs2); - LOG_TRACE(L"todo %S", __FUNCTION__); + if (voh == nullptr || state == nullptr) return getErr(ErrCode::_EINVAL); + if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; + + auto voice = (SceNgs2Handle_voice*)voh; + state->stateFlags = voice->state.stateFlags; return Ok; } EXPORT SYSV_ABI int32_t sceNgs2VoiceGetStateFlags(SceNgs2Handle* voh, uint32_t* flags) { - LOG_USE_MODULE(libSceNgs2); - LOG_TRACE(L"todo %S", __FUNCTION__); + if (voh == nullptr || flags == nullptr) return getErr(ErrCode::_EINVAL); + + if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; + + auto voice = (SceNgs2Handle_voice*)voh; + *flags = voice->state.stateFlags; return Ok; } @@ -465,158 +612,47 @@ EXPORT SYSV_ABI int32_t sceNgs2GeomResetSourceParam(SceNgs2GeomSourceParam* para return Ok; } -EXPORT SYSV_ABI int32_t sceNgs2RackCreate(SceNgs2Handle* sysh, uint32_t rackId, const SceNgs2RackOption* ropt, const SceNgs2ContextBufferInfo* cbi, - SceNgs2Handle** outh) { - LOG_USE_MODULE(libSceNgs2); - LOG_ERR(L"todo %S(%p, %d, %p, %p, %p)", __FUNCTION__, sysh, rackId, ropt, cbi, outh); - if (outh == nullptr) return Err::Ngs2::INVALID_OUT_ADDRESS; - if (sysh == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; - if (ropt != nullptr && ropt->size < sizeof(SceNgs2RackOption)) return Err::Ngs2::INVALID_OPTION_SIZE; - if (cbi == nullptr || cbi->hostBuffer == nullptr || cbi->hostBufferSize < sizeof(SceNgs2Handle)) return Err::Ngs2::INVALID_BUFFER_ADDRESS; - - *outh = (SceNgs2Handle*)cbi->hostBuffer; - (*outh)->allocSet = false; - (*outh)->alloc.allocHandler = nullptr; - (*outh)->alloc.freeHandler = nullptr; - (*outh)->alloc.userData = nullptr; - (*outh)->owner = sysh; - - if (ropt != nullptr) { - (*outh)->un.rack.info.maxPorts = ropt->maxPorts; - (*outh)->un.rack.info.maxMatrices = ropt->maxMatrices; - (*outh)->un.rack.info.maxGrainSamples = ropt->maxGrainSamples; - (*outh)->un.rack.info.maxVoices = ropt->maxVoices; - } else { - (*outh)->un.rack.info.maxPorts = 1; - (*outh)->un.rack.info.maxMatrices = 1; - (*outh)->un.rack.info.maxGrainSamples = 1; - (*outh)->un.rack.info.maxVoices = 1; - } - - auto vo = (*outh)->un.rack.voices = new SceNgs2Handle; - vo->allocSet = false; - vo->alloc.allocHandler = nullptr; - vo->alloc.freeHandler = nullptr; - vo->alloc.userData = nullptr; - - return (*outh) != nullptr ? Ok : Err::Ngs2::FAIL; -} - -EXPORT SYSV_ABI int32_t sceNgs2RackCreateWithAllocator(SceNgs2Handle* sysh, uint32_t rackId, const SceNgs2RackOption* ro, const SceNgs2BufferAllocator* alloc, - SceNgs2Handle** outh) { - if (sysh == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; - if (alloc == nullptr) return Err::Ngs2::INVALID_BUFFER_ALLOCATOR; - LOG_USE_MODULE(libSceNgs2); - LOG_TRACE(L"todo %S", __FUNCTION__); - - SceNgs2ContextBufferInfo cbi = { - .hostBuffer = nullptr, - .hostBufferSize = sizeof(SceNgs2Handle), - .userData = alloc->userData, - }; - - if (auto ret = alloc->allocHandler(&cbi)) { - LOG_ERR(L"Ngs2Rack: Allocation failed!"); - return ret; - } - - *outh = (SceNgs2Handle*)cbi.hostBuffer; - (*outh)->owner = sysh; - (*outh)->allocSet = true; - (*outh)->alloc = *alloc; - (*outh)->cbi = cbi; - - cbi.hostBufferSize = sizeof(SceNgs2Handle) * ((ro != nullptr) ? ro->maxVoices : 1); - - if (auto ret = alloc->allocHandler(&cbi)) { - LOG_ERR(L"Ngs2Rack: Voice allocation failed"); - return ret; - } - - auto vo = (*outh)->un.rack.voices = (SceNgs2Handle*)cbi.hostBuffer; - vo->allocSet = true; - vo->alloc = *alloc; - - return Ok; -} - EXPORT SYSV_ABI int32_t sceNgs2RackDestroy(SceNgs2Handle* rh, SceNgs2ContextBufferInfo* cbi) { - if (rh == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; - if (rh->allocSet) { - cbi->hostBufferSize = sizeof(SceNgs2Handle); - cbi->hostBuffer = rh->un.rack.voices; - if (auto ret = rh->alloc.freeHandler(cbi)) return ret; - cbi->hostBuffer = rh; - if (auto ret = rh->alloc.freeHandler(cbi)) return ret; - } else { - if (rh->un.rack.voices != nullptr) delete rh->un.rack.voices; - } - - return Ok; -} - -EXPORT SYSV_ABI int32_t sceNgs2RackQueryBufferSize(uint32_t rackId, const SceNgs2RackOption* ro, SceNgs2ContextBufferInfo* cbi) { - cbi->hostBufferSize = sizeof(SceNgs2Handle); - return Ok; -} - -EXPORT SYSV_ABI int32_t sceNgs2SystemCreateWithAllocator(const SceNgs2SystemOption* sysopt, SceNgs2BufferAllocator* alloc, SceNgs2Handle** outh) { - LOG_USE_MODULE(libSceNgs2); - LOG_ERR(L"todo %S(%p, %p, %p)", __FUNCTION__, sysopt, alloc, outh); - if (alloc == nullptr || alloc->allocHandler == nullptr) return Err::Ngs2::INVALID_BUFFER_ALLOCATOR; - if (outh == nullptr) return Err::Ngs2::INVALID_OUT_ADDRESS; - if (sysopt != nullptr && sysopt->size < sizeof(SceNgs2SystemOption)) return Err::Ngs2::INVALID_OPTION_SIZE; - - SceNgs2ContextBufferInfo cbi = { - .hostBuffer = nullptr, - .hostBufferSize = sizeof(SceNgs2Handle), - .userData = alloc->userData, - }; - - if (auto ret = alloc->allocHandler(&cbi)) { - LOG_ERR(L"Ngs2System: Allocation failed!"); - return ret; - } - - *outh = (SceNgs2Handle*)cbi.hostBuffer; - (*outh)->owner = nullptr; - (*outh)->allocSet = true; - (*outh)->alloc = *alloc; - (*outh)->cbi = cbi; + if (rh == nullptr) return Err::Ngs2::INVALID_RACK_HANDLE; + boost::unique_lock lock(MUTEX_INT); - return Ok; -} + auto rack = (SceNgs2Handle_rack*)rh; -EXPORT SYSV_ABI int32_t sceNgs2SystemCreate(const SceNgs2SystemOption* sysopt, const SceNgs2ContextBufferInfo* cbi, SceNgs2Handle** outh) { - LOG_USE_MODULE(libSceNgs2); - LOG_ERR(L"todo %S(%p, %p, %p)", __FUNCTION__, sysopt, cbi, outh); - if (outh == nullptr) return Err::Ngs2::INVALID_OUT_ADDRESS; - if (sysopt != nullptr && sysopt->size < sizeof(SceNgs2SystemOption)) return Err::Ngs2::INVALID_OPTION_SIZE; - if (cbi == nullptr || cbi->hostBuffer == nullptr || cbi->hostBufferSize < sizeof(SceNgs2Handle)) return Err::Ngs2::INVALID_BUFFER_ADDRESS; + auto freeHandler = rack->parent->alloc.freeHandler; - *outh = (SceNgs2Handle*)cbi->hostBuffer; - (*outh)->allocSet = false; - (*outh)->owner = nullptr; + int32_t ret = Ok; + if (freeHandler != nullptr) { + SceNgs2ContextBufferInfo cbi = { + .hostBuffer = rack, + .hostBufferSize = sizeof(SceNgs2Handle_rack) + (rack->options.maxVoices * sizeof(SceNgs2Handle_voice)), + }; + rack->~SceNgs2Handle_rack(); + ret = freeHandler(&cbi); + } else + rack->~SceNgs2Handle_rack(); - return (*outh) != nullptr ? Ok : Err::Ngs2::FAIL; + return ret; } EXPORT SYSV_ABI int32_t sceNgs2SystemDestroy(SceNgs2Handle* sysh, SceNgs2ContextBufferInfo* cbi) { if (sysh == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; - if (sysh->allocSet) { - cbi->hostBuffer = sysh; - cbi->hostBufferSize = sizeof(SceNgs2Handle); - if (auto ret = sysh->alloc.freeHandler(cbi)) return ret; - } else { - delete sysh; - } + boost::unique_lock lock(MUTEX_INT); - return Ok; -} + auto system = (SceNgs2Handle_system*)sysh; -EXPORT SYSV_ABI int32_t sceNgs2SystemQueryBufferSize(const SceNgs2SystemOption* sysopt, SceNgs2ContextBufferInfo* cbi) { - if (cbi == nullptr) return Err::Ngs2::INVALID_BUFFER_ADDRESS; - cbi->hostBufferSize = sizeof(SceNgs2Handle); - return Ok; + auto freeHandler = system->alloc.freeHandler; + + int32_t ret = Ok; + if (freeHandler != nullptr) { + SceNgs2ContextBufferInfo cbi = { + .hostBuffer = system, + .hostBufferSize = sizeof(SceNgs2Handle_system), + }; + system->~SceNgs2Handle_system(); + ret = freeHandler(&cbi); + } else + system->~SceNgs2Handle_system(); + + return ret; } } diff --git a/modules/libSceNgs2/readFuncs.cpp b/modules/libSceNgs2/readFuncs.cpp new file mode 100644 index 00000000..b389c9c4 --- /dev/null +++ b/modules/libSceNgs2/readFuncs.cpp @@ -0,0 +1,160 @@ +#include "readFuncs.h" + +#include "core/fileManager/ifile.h" +#include "core/kernel/filesystem.h" +#include "logging.h" +extern "C" { +#include +} +#include +#include +LOG_DEFINE_MODULE(libSceNgs2); + +namespace { +static SceNgs2ChannelsCount convChanCount(int num) { + LOG_USE_MODULE(libSceNgs2); + + switch (num) { + case 1: return SceNgs2ChannelsCount::CH_1_0; + + case 2: return SceNgs2ChannelsCount::CH_2_0; + + case 6: return SceNgs2ChannelsCount::CH_5_1; + + case 8: return SceNgs2ChannelsCount::CH_7_1; + } + + LOG_CRIT(L"Invalid channels count sent to ParseChanCount!"); + return SceNgs2ChannelsCount::INVALID; +} + +static SceNgs2WaveFormType convWaveType(AVCodecID codec) { + switch (codec) { + case AVCodecID::AV_CODEC_ID_PCM_S8: return SceNgs2WaveFormType::PCM_I8; + + case AVCodecID::AV_CODEC_ID_PCM_U8: return SceNgs2WaveFormType::PCM_U8; + + case AVCodecID::AV_CODEC_ID_ATRAC9: return SceNgs2WaveFormType::ATRAC9; + + default: return SceNgs2WaveFormType::NONE; + } +} +} // namespace + +int readFunc_linearBuffer(void* userData_, uint8_t* buf, int size) { + auto userData = (userData_inerBuffer*)userData_; + + int const dataLeft = userData->size - userData->curOffset; + auto readSize = std::min(dataLeft, size); + + if (readSize > 0) { + userData->curOffset += readSize; + ::memcpy(buf, userData->ptr, readSize); + } + + return readSize; +} + +int64_t seekFunc_linearBuffer(void* userData_, int64_t offset, int whence) { + auto userData = (userData_inerBuffer*)userData_; + + switch ((SceWhence)whence) { + case SceWhence::beg: userData->curOffset = offset; break; + case SceWhence::cur: + if (userData->curOffset < offset) + userData->curOffset = 0; + else + userData->curOffset += offset; + break; + case SceWhence::end: userData->curOffset = std::min(userData->size, userData->size + offset); break; + } + + return userData->curOffset; +} + +int readFunc_file(void* userData_, uint8_t* buf, int size) { + auto handle = (int&)userData_; + return filesystem::read(handle, buf, size); +} + +int64_t seekFunc_file(void* userData_, int64_t offset, int whence) { + auto handle = (int&)userData_; + return filesystem::lseek(handle, offset, whence); +} + +int readFunc_user(void* userData_, uint8_t* buf, int size) { + auto userData = (userData_user*)userData_; + + auto read = userData->func(userData->userData, userData->curOffset, buf, size); + userData->curOffset += read; + return read; +} + +int64_t seekFunc_user(void* userData_, int64_t offset, int whence) { + auto userData = (userData_user*)userData_; + + return 0; // undefined +} + +int32_t parseWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData, SceNgs2WaveformFormat* wf) { + LOG_USE_MODULE(libSceNgs2); + + std::list> cleanup; + + // Setup + auto aBufferIo = (uint8_t*)av_malloc(4096 + AV_INPUT_BUFFER_PADDING_SIZE); + + AVIOContext* avioctx = avio_alloc_context(aBufferIo, 4096, 0, userData, readFunc, nullptr, seekFunc); + + cleanup.emplace_back([&] { av_free(avioctx); }); + cleanup.emplace_back([&] { av_free(aBufferIo); }); + + // Open the input + AVFormatContext* fmtctx = avformat_alloc_context(); + cleanup.emplace_back([&] { avformat_free_context(fmtctx); }); + + fmtctx->pb = avioctx; + fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; + + int ret = avformat_open_input(&fmtctx, "nullptr", nullptr, nullptr); + if (ret != 0) { + LOG_ERR(L"ParseRIFF: ffmpeg failed to read passed data: %d", ret); + return Err::Ngs2::FAIL; + } + cleanup.emplace_back([&] { avformat_close_input(&fmtctx); }); + + AVStream* astream = nullptr; + AVCodec const* codec = nullptr; + + { + auto stream_idx = av_find_best_stream(fmtctx, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0); + + if (stream_idx < 0) { + LOG_ERR(L"ParseRIFF: no audio stream"); + return Err::Ngs2::FAIL; + } + + astream = fmtctx->streams[stream_idx]; + } + + // Fill data + wf->info.type = convWaveType(astream->codecpar->codec_id); + wf->info.sampleRate = astream->codecpar->sample_rate; + wf->info.channelsCount = convChanCount(astream->codecpar->ch_layout.nb_channels); + + // These are unknown for now + wf->loopBeginPos = wf->loopEndPos = 0; + + wf->samplesCount = astream->nb_frames; + + auto const totalSize = seekFunc(userData, 0, (int)SceWhence::end); + + wf->offset = 0; + wf->size = totalSize; + + auto& block = wf->block[0]; + block.offset = 0; + block.size = totalSize; + wf->numBlocks = 1; + return Ok; +} \ No newline at end of file diff --git a/modules/libSceNgs2/readFuncs.h b/modules/libSceNgs2/readFuncs.h new file mode 100644 index 00000000..918b4115 --- /dev/null +++ b/modules/libSceNgs2/readFuncs.h @@ -0,0 +1,26 @@ +#pragma once +#include "types.h" + +using funcReadBuf_t = int (*)(void*, uint8_t*, int); +using funcSeekBuf_t = int64_t (*)(void*, int64_t, int); + +struct userData_user { + SceWaveformUserFunc func; + uintptr_t userData; + size_t curOffset; +}; + +struct userData_inerBuffer { + const void* ptr; + size_t size; + size_t curOffset; +}; + +int readFunc_linearBuffer(void* userData_, uint8_t* buf, int size); +int64_t seekFunc_linearBuffer(void* userData_, int64_t offset, int whence); +int readFunc_file(void* userData_, uint8_t* buf, int size); +int64_t seekFunc_file(void* userData_, int64_t offset, int whence); +int readFunc_user(void* userData_, uint8_t* buf, int size); +int64_t seekFunc_user(void* userData_, int64_t offset, int whence); + +int32_t parseWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData, SceNgs2WaveformFormat* wf); \ No newline at end of file diff --git a/modules/libSceNgs2/reader.cpp b/modules/libSceNgs2/reader.cpp new file mode 100644 index 00000000..295aa805 --- /dev/null +++ b/modules/libSceNgs2/reader.cpp @@ -0,0 +1,127 @@ +#include "reader.h" + +extern "C" { +#include +#include +#include +} + +#include "logging.h" +#include "readFuncs.h" +#include "types.h" + +#include +#include + +LOG_DEFINE_MODULE(libSceNgs2); + +namespace { +struct PImpl { + std::list> cleanup; + + userData_inerBuffer userData = {}; + + AVStream* astream = nullptr; + AVCodec const* codec = nullptr; + int stream_idx = 0; + + AVCodecContext* codecContext = nullptr; + + AVFrame* frame = nullptr; + SwrContext* swrCtx = nullptr; +}; +} // namespace + +Reader::Reader() { + m_pimpl = std::make_unique().release(); +} + +Reader::~Reader() { + delete (PImpl*)m_pimpl; +} + +bool Reader::init(void const* data, size_t size) { + LOG_USE_MODULE(libSceNgs2); + + auto pimpl = (PImpl*)m_pimpl; + + auto& cleanup = pimpl->cleanup; + auto& userData = pimpl->userData; + + userData.ptr = data; + userData.size = size; + userData.curOffset = 0; + + // Init Setup + auto aBufferIo = (uint8_t*)av_malloc(4096 + AV_INPUT_BUFFER_PADDING_SIZE); + + AVIOContext* avioctx = avio_alloc_context(aBufferIo, 4096, 0, &userData, readFunc_linearBuffer, nullptr, seekFunc_linearBuffer); + + cleanup.emplace_back([&] { av_free(avioctx); }); + cleanup.emplace_back([&] { av_free(aBufferIo); }); + + // Open the input + AVFormatContext* fmtctx = avformat_alloc_context(); + cleanup.emplace_back([&] { avformat_free_context(fmtctx); }); + + fmtctx->pb = avioctx; + fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; + + int ret = avformat_open_input(&fmtctx, "nullptr", nullptr, nullptr); + if (ret != 0) { + LOG_ERR(L"Reader: ffmpeg failed to read passed data: %d", ret); + return false; + } + cleanup.emplace_back([&] { avformat_close_input(&fmtctx); }); + + pimpl->stream_idx = av_find_best_stream(fmtctx, AVMEDIA_TYPE_AUDIO, -1, -1, &pimpl->codec, 0); + + if (pimpl->stream_idx < 0) { + LOG_ERR(L"Reader: no audio stream"); + return false; + } + + pimpl->astream = fmtctx->streams[pimpl->stream_idx]; + + pimpl->codecContext = avcodec_alloc_context3(pimpl->codec); + if (auto err = avcodec_parameters_to_context(pimpl->codecContext, pimpl->astream->codecpar); err != 0) { + LOG_ERR(L"Reader: avcodec_parameters_to_context err:%d", err); + return false; + } + cleanup.emplace_back([&] { avcodec_free_context(&pimpl->codecContext); }); + + // Setup multithreading + if (pimpl->codec->capabilities | AV_CODEC_CAP_FRAME_THREADS) + pimpl->codecContext->thread_type = FF_THREAD_FRAME; + else if (pimpl->codec->capabilities | AV_CODEC_CAP_SLICE_THREADS) + pimpl->codecContext->thread_type = FF_THREAD_SLICE; + else + pimpl->codecContext->thread_count = 1; // don't use multithreading + // - + + if (auto err = avcodec_open2(pimpl->codecContext, pimpl->codec, NULL); err < 0) { + LOG_ERR(L"Reader: avcodec_open2 err:%d", err); + return false; + } + + if (swr_alloc_set_opts2(&pimpl->swrCtx, &pimpl->codecContext->ch_layout, AVSampleFormat::AV_SAMPLE_FMT_S16, pimpl->codecContext->sample_rate, + &pimpl->codecContext->ch_layout, pimpl->codecContext->sample_fmt, pimpl->codecContext->sample_rate, 0, NULL)) { + LOG_ERR(L"Reader:Couldn't alloc swr"); + return false; + } + + swr_init(pimpl->swrCtx); + cleanup.emplace_back([&] { swr_free(&pimpl->swrCtx); }); + + pimpl->frame = av_frame_alloc(); + cleanup.emplace_back([&] { av_frame_free(&pimpl->frame); }); + + m_isInit = true; + + return true; +} + +bool Reader::getAudio(void* buffer, size_t bufferSize) { + std::memset(buffer, 0, bufferSize); + return true; +} \ No newline at end of file diff --git a/modules/libSceNgs2/reader.h b/modules/libSceNgs2/reader.h new file mode 100644 index 00000000..7e0dc174 --- /dev/null +++ b/modules/libSceNgs2/reader.h @@ -0,0 +1,14 @@ +#pragma once + +class Reader { + void* m_pimpl; + bool m_isInit = false; + + public: + Reader(); + ~Reader(); + + bool init(void const* data, size_t size); + + bool getAudio(void* buffer, size_t bufferSize); +}; \ No newline at end of file diff --git a/modules/libSceNgs2/temp.txt b/modules/libSceNgs2/temp.txt new file mode 100644 index 00000000..c1f7c8b6 --- /dev/null +++ b/modules/libSceNgs2/temp.txt @@ -0,0 +1,34 @@ +// create +result = sceNgs2SystemCreateWithAllocator(NULL, &allocator, &m_systemHandle); +result = sceNgs2RackCreateWithAllocator(m_systemHandle, SCE_NGS2_RACK_ID_MASTERING, NULL, &allocator, &m_masteringRackHandle); +result = sceNgs2RackCreateWithAllocator(m_systemHandle, SCE_NGS2_RACK_ID_SAMPLER, NULL, &allocator, &m_samplerRackHandle); + +// Voice : Audio source +sceNgs2RackGetVoiceHandle(m_samplerRackHandle, 0, &m_samplerVoiceHandle); +sceNgs2SamplerVoiceSetup(m_samplerVoiceHandle, &m_waveformInfo.format, 0); +sceNgs2SamplerVoiceAddWaveformBlocks(m_samplerVoiceHandle, m_waveformData, m_waveformInfo.aBlock, m_waveformInfo.numBlocks, 0); +sceNgs2VoicePatch(m_samplerVoiceHandle, 0, m_masteringVoiceHandle, 0); + +result = sceNgs2VoiceKickEvent(m_samplerVoiceHandle, SCE_NGS2_VOICE_EVENT_PLAY); // sceNgs2VoiceControl + + + +// ### Read Wave +result = fileLoad(WAVEFORM_PATH, &m_waveformData, &m_waveformDataSize); +if (result < SCE_OK) { + goto failed; +} + +result = sceNgs2ParseWaveformData(m_waveformData, m_waveformDataSize, &m_waveformInfo); +if (result < 0) { + goto failed; +} +// --- + +sceNgs2RackGetVoiceHandle(m_samplerRackHandle, 0, &m_samplerVoiceHandle); +sceNgs2SamplerVoiceSetup(m_samplerVoiceHandle, &m_waveformInfo.format, 0); +sceNgs2SamplerVoiceAddWaveformBlocks(m_samplerVoiceHandle, m_waveformData, m_waveformInfo.aBlock, m_waveformInfo.numBlocks, 0); +sceNgs2VoicePatch(m_samplerVoiceHandle, 0, m_masteringVoiceHandle, 0); + + +sceNgs2SystemRender() // takes data \ No newline at end of file diff --git a/modules/libSceNgs2/types.h b/modules/libSceNgs2/types.h index 65cb3573..ecbe3490 100644 --- a/modules/libSceNgs2/types.h +++ b/modules/libSceNgs2/types.h @@ -1,6 +1,31 @@ #pragma once #include "..\libSceCommonDialog\types.h" #include "codes.h" +#include "utility/utility.h" + +#include + +union SceNgs2VoiceStateFlags { + uint32_t data; + + struct { + bool Inuse : 1; + bool Playing : 1; + bool Paused : 1; + bool Stopped : 1; + bool Error : 1; + bool Empty : 1; + } bits; +}; + +enum class SceNgs2VoiceEvent { + Play, + Stop, + Stop_imm, + Kill, + Pause, + Resume, +}; enum class SceNgs2WaveFormType : uint32_t { NONE = 0, @@ -41,7 +66,8 @@ enum class SceNgs2ChannelsCount : uint32_t { INVALID = 0xFFFFFFFF }; -enum class SceNgs2VoiceParam : uint32_t { +// Voice events +enum class SceNgs2VoiceParam : uint16_t { SET_MATRIX_LEVELS = 1, SET_PORT_VOLUME, SET_PORT_MATRIX, @@ -51,6 +77,53 @@ enum class SceNgs2VoiceParam : uint32_t { SET_CALLBACK, }; +// Master events +enum class SceNgs2MasteringParam : uint16_t { + SETUP, + SET_MATRIX, + SET_LFE, + SET_LIMITER, + SET_GAIN, + SET_OUTPUT, + SET_PEAK_METER, +}; + +// sampler events +enum class SceNgs2SamplerParam : uint16_t { + SETUP, + ADD_WAVEFORM_BLOCKS, + REPLACE_WAVEFORM_ADDRESS, + SET_WAVEFORM_FRAME_OFFSET, + EXIT_LOOP, + SET_PITCH, + SET_ENVELOPE, + SET_DISTORTION, + SET_USER_FX, + SET_PEAK_METER, + SET_FILTER, +}; +// Submixer events +enum class SceNgs2SubmixerParam : uint16_t { + SETUP, + SET_ENVELOPE, + SET_COMPRESSOR, + SET_DISTORTION, + SET_USER_FX, + SET_PEAK_METER, + SET_FILTER, +}; + +class Reader; + +struct SceNgs2VoiceHandle { + SceNgs2VoiceHandle() = default; + ~SceNgs2VoiceHandle() = default; + + SceNgs2VoiceStateFlags state = {0}; + + Reader* reader = nullptr; +}; + struct SceNgs2ContextBufferInfo { void* hostBuffer; size_t hostBufferSize; @@ -59,8 +132,8 @@ struct SceNgs2ContextBufferInfo { }; struct SceNgs2BufferAllocator { - int32_t SYSV_ABI (*allocHandler)(SceNgs2ContextBufferInfo*); - int32_t SYSV_ABI (*freeHandler)(SceNgs2ContextBufferInfo*); + int32_t SYSV_ABI (*allocHandler)(SceNgs2ContextBufferInfo*) = nullptr; + int32_t SYSV_ABI (*freeHandler)(SceNgs2ContextBufferInfo*) = nullptr; void* userData; }; @@ -105,30 +178,81 @@ struct SceNgs2SystemInfo { uint32_t numGrainSamples; }; -struct SceNgs2SystemHandle { - SceNgs2SystemInfo info; -}; +struct SceNgs2RackOption { + size_t size = sizeof(SceNgs2RackOption); -struct SceNgs2RackHandle { - SceNgs2RackInfo info; - SceNgs2Handle* voices; + char name[SCE_NGS2_RACK_NAME_LENGTH] = "\0"; + uint32_t flags; + uint32_t maxGrainSamples = 1; + uint32_t maxVoices = 1; + ; + uint32_t maxInputDelayBlocks = 1; + ; + uint32_t maxMatrices = 1; + ; + uint32_t maxPorts = 1; + ; + uint32_t aReserved[20]; }; -struct SceNgs2VoiceHandle { - std::vector* data; +struct SceNgs2VoiceState { + uint32_t stateFlags = 0; }; +enum class SceNgs2HandleType { System, Rack, Voice }; + +struct SceNgs2Handle_rack; + struct SceNgs2Handle { - SceNgs2Handle* owner; - bool allocSet; - SceNgs2BufferAllocator alloc; - SceNgs2ContextBufferInfo cbi; + SceNgs2HandleType const type; + + SceNgs2Handle(SceNgs2HandleType type): type(type) {} - union _ngsTypes { - SceNgs2SystemHandle sys; - SceNgs2RackHandle rack; - SceNgs2VoiceHandle voice; - } un; + virtual ~SceNgs2Handle() = default; +}; + +struct SceNgs2Handle_system: public SceNgs2Handle { + SceNgs2BufferAllocator alloc; + + // Racks + SceNgs2Handle_rack* mastering = nullptr; + SceNgs2Handle_rack* sampler = nullptr; + SceNgs2Handle_rack* submixer = nullptr; + + // - + + SceNgs2Handle_system(SceNgs2BufferAllocator const* alloc_): SceNgs2Handle(SceNgs2HandleType::System) { + if (alloc_ != nullptr) alloc = *alloc_; + } + + virtual ~SceNgs2Handle_system() = default; +}; + +struct SceNgs2Handle_voice: public SceNgs2Handle { + SceNgs2Handle_rack* parent; + SceNgs2VoiceState state {}; + + Reader* reader = nullptr; // optional, depends on racktype + + SceNgs2Handle_voice(SceNgs2Handle_rack* parent): SceNgs2Handle(SceNgs2HandleType::Voice), parent(parent) {} + + virtual ~SceNgs2Handle_voice(); +}; + +struct SceNgs2Handle_rack: public SceNgs2Handle { + uint32_t const rackId; + + SceNgs2Handle_system* parent; + + SceNgs2RackOption options; + SceNgs2Handle_voice* voices; + + SceNgs2Handle_rack(SceNgs2Handle_system* parent, SceNgs2RackOption const* options_, uint32_t rackId) + : SceNgs2Handle(SceNgs2HandleType::Rack), rackId(rackId), parent(parent) { + if (options_ != nullptr) memcpy(&options, &options_, sizeof(SceNgs2RackOption)); + } + + virtual ~SceNgs2Handle_rack() = default; }; struct SceNgs2RenderBufferInfo { @@ -280,22 +404,6 @@ struct SceNgs2VoiceCallbackParam { uint32_t reserved; }; -struct SceNgs2VoiceState { - uint32_t stateFlags; -}; - -struct SceNgs2RackOption { - size_t size; - char name[SCE_NGS2_RACK_NAME_LENGTH]; - uint32_t flags; - uint32_t maxGrainSamples; - uint32_t maxVoices; - uint32_t maxInputDelayBlocks; - uint32_t maxMatrices; - uint32_t maxPorts; - uint32_t aReserved[20]; -}; - struct SceNgs2CustomModuleInfo { uint32_t moduleId; uint32_t sourceBufferId; From 980e6f90f0243368b60ad2f0211c4f2067f3edab Mon Sep 17 00:00:00 2001 From: Martin Baliet Date: Tue, 7 May 2024 16:07:14 +0200 Subject: [PATCH 05/19] ngs2| dump --- modules/libSceNgs2/codes.h | 3 + modules/libSceNgs2/entry.cpp | 195 ++++++++++++++++++++++++------- modules/libSceNgs2/readFuncs.cpp | 20 +++- modules/libSceNgs2/reader.cpp | 186 +++++++++++++++++++---------- modules/libSceNgs2/reader.h | 7 +- modules/libSceNgs2/types.h | 81 +++++++------ modules/libSceNpParty/entry.cpp | 2 +- 7 files changed, 352 insertions(+), 142 deletions(-) diff --git a/modules/libSceNgs2/codes.h b/modules/libSceNgs2/codes.h index 045f4900..a0b2dfa9 100644 --- a/modules/libSceNgs2/codes.h +++ b/modules/libSceNgs2/codes.h @@ -31,6 +31,9 @@ constexpr uint16_t SCE_NGS2_RACK_ID_SAMPLER = 0x1000; constexpr uint16_t SCE_NGS2_RACK_ID_SUBMIXER = 0x2000; constexpr uint16_t SCE_NGS2_RACK_ID_MASTERING = 0x3000; +constexpr uint16_t SCE_NGS2_RACK_ID_REVERB = 0x2001; +constexpr uint16_t SCE_NGS2_RACK_ID_EQ = 0x2002; + constexpr uint16_t SCE_NGS2_RACK_ID_CUSTOM_SAMPLER = 0x4001; constexpr uint16_t SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER = 0x4002; constexpr uint16_t SCE_NGS2_RACK_ID_CUSTOM_MASTERING = 0x4003; \ No newline at end of file diff --git a/modules/libSceNgs2/entry.cpp b/modules/libSceNgs2/entry.cpp index f0d789c3..ffce1b15 100644 --- a/modules/libSceNgs2/entry.cpp +++ b/modules/libSceNgs2/entry.cpp @@ -1,8 +1,3 @@ -extern "C" { -#include -#include -#include -} #include "core/fileManager/ifile.h" #include "core/kernel/filesystem.h" #include "core/kernel/pthread.h" @@ -12,12 +7,22 @@ extern "C" { #include "types.h" #include +#include LOG_DEFINE_MODULE(libSceNgs2); namespace { static boost::mutex MUTEX_INT; +struct Impl { + std::set handles; +}; + +Impl* getPimpl() { + static Impl pimpl; + return &pimpl; +} + int32_t _voiceControlWaveformBlock(SceNgs2Handle* voh, const SceNgs2SamplerVoiceWaveformBlocksParam* svwfbp) { LOG_USE_MODULE(libSceNgs2); @@ -28,12 +33,20 @@ int32_t _voiceControlWaveformBlock(SceNgs2Handle* voh, const SceNgs2SamplerVoice auto voice = (SceNgs2Handle_voice*)voh; voice->reader = std::make_unique().release(); - voice->reader->init(svwfbp->data, svwfbp->aBlock[0].size); + if (!voice->reader->init(svwfbp)) { + return Err::Ngs2::INVALID_WAVEFORM_DATA; + } + voice->state.bits.Empty = false; + + LOG_DEBUG(L"waveptr voice:0x%08llx %llx", (uint64_t)voh, svwfbp->data); return Ok; } int32_t voiceControl_voice(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; + auto voice = (SceNgs2Handle_voice*)voh; + switch ((SceNgs2VoiceParam)(phead->id & 0xFFFF)) { case SceNgs2VoiceParam::SET_MATRIX_LEVELS: { } break; @@ -46,6 +59,8 @@ int32_t voiceControl_voice(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phea case SceNgs2VoiceParam::PATCH: { } break; case SceNgs2VoiceParam::KICK_EVENT: { + auto item = (SceNgs2VoiceEventParam*)phead; + voice->ev_KickEvent((SceNgs2VoiceEvent)item->eventId); } break; case SceNgs2VoiceParam::SET_CALLBACK: { } break; @@ -73,9 +88,26 @@ int32_t voiceControl_mastering(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* return Ok; } +int32_t voiceControl_reverb(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + return Ok; +} + +int32_t voiceControl_equalizer(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + return Ok; +} + int32_t voiceControl_sampler(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + LOG_USE_MODULE(libSceNgs2); + LOG_INFO(L"voice_sampler id:%u type:%u", phead->id & 0xFFFF, voh->type); + + if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; + + auto voice = (SceNgs2Handle_voice*)voh; + switch ((SceNgs2SamplerParam)(phead->id & 0xFFFF)) { case SceNgs2SamplerParam::SETUP: { + auto item = (SceNgs2SamplerVoiceSetupParam*)phead; + voice->info = item->format; } break; case SceNgs2SamplerParam::ADD_WAVEFORM_BLOCKS: { return _voiceControlWaveformBlock(voh, (const SceNgs2SamplerVoiceWaveformBlocksParam*)phead); @@ -127,6 +159,35 @@ SceNgs2Handle_voice::~SceNgs2Handle_voice() { if (reader != nullptr) delete reader; } +void SceNgs2Handle_voice::ev_KickEvent(SceNgs2VoiceEvent id) { + state.bits.Inuse = true; + switch (id) { + case SceNgs2VoiceEvent::Play: { + state.bits.Playing = true; + } break; + case SceNgs2VoiceEvent::Stop: { + state.bits.Stopped = true; + state.bits.Playing = false; + } break; + case SceNgs2VoiceEvent::Stop_imm: { + state.bits.Stopped = true; + state.bits.Playing = false; + } break; + case SceNgs2VoiceEvent::Kill: { + state.bits.Stopped = true; + state.bits.Playing = false; + } break; + case SceNgs2VoiceEvent::Pause: { + state.bits.Paused = true; + } break; + case SceNgs2VoiceEvent::Resume: { + state.bits.Paused = false; + } break; + } + LOG_USE_MODULE(libSceNgs2); + LOG_DEBUG(L"set state voice:0x%08llx id:%u state:%x", (uint64_t)this, id, state.data); +} + extern "C" { EXPORT const char* MODULE_NAME = "libSceNgs2"; @@ -168,7 +229,9 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemCreateWithAllocator(const SceNgs2SystemOpti } *outh = new (cbi.hostBuffer) SceNgs2Handle_system(alloc); + getPimpl()->handles.emplace(*outh); + LOG_DEBUG(L"-> System: 0x%08llx", (uint64_t)*outh); return Ok; } @@ -181,7 +244,9 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemCreate(const SceNgs2SystemOption* sysopt, c if (cbi == nullptr || cbi->hostBuffer == nullptr || cbi->hostBufferSize < sizeof(SceNgs2Handle)) return Err::Ngs2::INVALID_BUFFER_ADDRESS; *outh = new (cbi->hostBuffer) SceNgs2Handle_system(nullptr); + getPimpl()->handles.emplace(*outh); + LOG_DEBUG(L"-> System: 0x%08llx", (uint64_t)*outh); return (*outh) != nullptr ? Ok : Err::Ngs2::FAIL; } @@ -197,6 +262,7 @@ EXPORT SYSV_ABI int32_t sceNgs2RackCreate(SceNgs2Handle* sysh, uint32_t rackId, auto system = (SceNgs2Handle_system*)sysh; *outh = new (cbi->hostBuffer) SceNgs2Handle_rack(system, ropt, rackId); + getPimpl()->handles.emplace(*outh); auto rack = (SceNgs2Handle_rack*)(*outh); @@ -219,11 +285,16 @@ EXPORT SYSV_ABI int32_t sceNgs2RackCreate(SceNgs2Handle* sysh, uint32_t rackId, system->sampler = rack; } else if (rackId == SCE_NGS2_RACK_ID_SUBMIXER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER) { system->submixer = rack; + } else if (rackId == SCE_NGS2_RACK_ID_REVERB) { + system->reverb = rack; + } else if (rackId == SCE_NGS2_RACK_ID_EQ) { + system->equalizer = rack; } else { LOG_ERR(L"-> Rack: undefined rackid %u", rackId); return Err::Ngs2::FAIL; } + LOG_DEBUG(L"-> Rack: system:0x%08llx rack:0x%08llx id:0x%x", (uint64_t)sysh, (uint64_t)*outh, rackId); return (*outh) != nullptr ? Ok : Err::Ngs2::FAIL; } @@ -250,6 +321,7 @@ EXPORT SYSV_ABI int32_t sceNgs2RackCreateWithAllocator(SceNgs2Handle* sysh, uint } *outh = new (cbi.hostBuffer) SceNgs2Handle_rack(system, ro, rackId); + getPimpl()->handles.emplace(*outh); auto rack = (SceNgs2Handle_rack*)(*outh); // Init voices @@ -258,7 +330,7 @@ EXPORT SYSV_ABI int32_t sceNgs2RackCreateWithAllocator(SceNgs2Handle* sysh, uint rack->voices = (SceNgs2Handle_voice*)addrVoices; - for (uint16_t n = 0; n < rack->options.maxVoices; ++n, addrVoices += sizeof(SceNgs2Handle_voice)) { + for (uint16_t n = 0; n < numVoices; ++n, addrVoices += sizeof(SceNgs2Handle_voice)) { auto pVoice = new ((void*)addrVoices) SceNgs2Handle_voice(rack); } } @@ -271,11 +343,16 @@ EXPORT SYSV_ABI int32_t sceNgs2RackCreateWithAllocator(SceNgs2Handle* sysh, uint system->sampler = rack; } else if (rackId == SCE_NGS2_RACK_ID_SUBMIXER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER) { system->submixer = rack; + } else if (rackId == SCE_NGS2_RACK_ID_REVERB) { + system->reverb = rack; + } else if (rackId == SCE_NGS2_RACK_ID_EQ) { + system->equalizer = rack; } else { LOG_ERR(L"-> Rack: undefined rackid %u", rackId); return Err::Ngs2::FAIL; } + LOG_DEBUG(L"-> Rack: system:0x%08llx rack:0x%08llx id:0x%x", (uint64_t)sysh, (uint64_t)*outh, rackId); return (*outh) != nullptr ? Ok : Err::Ngs2::FAIL; } @@ -358,18 +435,13 @@ EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformFile(const char* path, long offset, */ EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformUser(SceWaveformUserFunc func, uintptr_t userData_, SceNgs2WaveformFormat* wf) { - LOG_USE_MODULE(libSceNgs2); - LOG_ERR(L"todo %S", __FUNCTION__); - // todo parseWave uses seek for totalsize - return Err::Ngs2::FAIL; - - // if (func == nullptr) { - // return Err::Ngs2::INVALID_BUFFER_ADDRESS; - // } - // boost::unique_lock lock(MUTEX_INT); + if (func == nullptr) { + return Err::Ngs2::INVALID_BUFFER_ADDRESS; + } + boost::unique_lock lock(MUTEX_INT); - // userData_user userData {func, userData_, 0}; - // return parseWave(readFunc_user, seekFunc_user, (void*)&userData, wf); + userData_user userData {func, userData_, 0}; + return parseWave(readFunc_user, seekFunc_user, (void*)&userData, wf); } // - wave parsing @@ -382,8 +454,8 @@ EXPORT SYSV_ABI int32_t sceNgs2GetWaveformFrameInfo(const SceNgs2WaveformInfo* f boost::unique_lock lock(MUTEX_INT); if (outFrameSize) *outFrameSize = 1; // Some games crashes with divide by zero exception if we set 0 here - if (outNumFrameSamples) *outNumFrameSamples = 1; - if (outUnitsPerFrame) *outUnitsPerFrame = 1; + if (outNumFrameSamples) *outNumFrameSamples = 0; + if (outUnitsPerFrame) *outUnitsPerFrame = 0; if (outNumDelaySamples) *outNumDelaySamples = 0; return Ok; } @@ -430,7 +502,9 @@ EXPORT SYSV_ABI int32_t sceNgs2RackGetVoiceHandle(SceNgs2Handle* rh, uint32_t vo if (voiceId > rack->options.maxVoices) return Err::Ngs2::INVALID_VOICE_INDEX; *outh = (SceNgs2Handle*)((uint64_t)rack->voices + voiceId * sizeof(SceNgs2Handle_voice)); + getPimpl()->handles.emplace(*outh); + LOG_DEBUG(L"-> GetVoiceHandle: rack:0x%08llx id:%u @0x%08llx", (uint64_t)rh, voiceId, (uint64_t)*outh); return Ok; } @@ -490,17 +564,16 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemUnlock(SceNgs2Handle* sysh) { EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBufferInfo* rbi, int32_t count) { LOG_USE_MODULE(libSceNgs2); LOG_TRACE(L"todo %S", __FUNCTION__); - boost::unique_lock lock(MUTEX_INT); - // if (sysh == nullptr || sysh->un.rack.voices == nullptr || sysh->un.rack.voices->un.voice.reader == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; + auto system = (SceNgs2Handle_system*)sysh; + if (system == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; if (rbi->bufferPtr == nullptr) return Err::Ngs2::INVALID_BUFFER_ADDRESS; if (rbi->bufferSize == 0) return Err::Ngs2::INVALID_BUFFER_SIZE; if (rbi->waveType >= SceNgs2WaveFormType::MAX_TYPES) return Err::Ngs2::INVALID_WAVEFORM_TYPE; if (rbi->channelsCount > SceNgs2ChannelsCount::CH_7_1) return Err::Ngs2::INVALID_NUM_CHANNELS; - auto system = (SceNgs2Handle_system*)sysh; - if (system->sampler == nullptr) { + // for (int32_t i = 0; i < count; i++) { if (rbi[i].bufferPtr != nullptr) { std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); @@ -510,9 +583,9 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBu } else { for (int32_t i = 0; i < count; i++) { if (rbi[i].bufferPtr != nullptr) { - auto reader = system->sampler->voices[0].reader; - if (reader != nullptr) { - reader->getAudio(rbi[i].bufferPtr, rbi[i].bufferSize); + auto& samplerVoice = system->sampler->voices[0]; + if (samplerVoice.reader != nullptr) { + samplerVoice.reader->getAudio(&samplerVoice, rbi[i].bufferPtr, rbi[i].bufferSize); } else { std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); } @@ -556,35 +629,69 @@ EXPORT SYSV_ABI int32_t sceNgs2VoiceControl(SceNgs2Handle* voh, const SceNgs2Voi LOG_USE_MODULE(libSceNgs2); boost::unique_lock lock(MUTEX_INT); - uint16_t const rackId = phead->id >> 16; - - printf("0x%u 0x%u\n", rackId, (uint16_t)(phead->id & 0xffff)); // todo racecondition somewhere - if (rackId == SCE_NGS2_RACK_ID_VOICE) return voiceControl_voice(voh, phead); - if (rackId == SCE_NGS2_RACK_ID_MASTERING || rackId == SCE_NGS2_RACK_ID_CUSTOM_MASTERING) return voiceControl_mastering(voh, phead); - if (rackId == SCE_NGS2_RACK_ID_SAMPLER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SAMPLER) return voiceControl_sampler(voh, phead); - if (rackId == SCE_NGS2_RACK_ID_SUBMIXER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER) return voiceControl_submixer(voh, phead); - - LOG_ERR(L"Unhandled rackId: %08x", rackId); + if (voh == nullptr) return getErr(ErrCode::_EINVAL); + uint16_t const rackId_ = phead->id >> 16; + + auto curItem = phead; + int32_t ret = Ok; + while (true) { + uint16_t const rackId = curItem->id >> 16; + + if (rackId == SCE_NGS2_RACK_ID_VOICE) + ret = voiceControl_voice(voh, curItem); + else if (rackId == SCE_NGS2_RACK_ID_MASTERING || rackId == SCE_NGS2_RACK_ID_CUSTOM_MASTERING) + ret = voiceControl_mastering(voh, curItem); + else if (rackId == SCE_NGS2_RACK_ID_SAMPLER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SAMPLER) + ret = voiceControl_sampler(voh, curItem); + else if (rackId == SCE_NGS2_RACK_ID_SUBMIXER || rackId == SCE_NGS2_RACK_ID_CUSTOM_SUBMIXER) + ret = voiceControl_submixer(voh, curItem); + else if (rackId == SCE_NGS2_RACK_ID_REVERB) + ret = voiceControl_reverb(voh, curItem); + else if (rackId == SCE_NGS2_RACK_ID_EQ) + ret = voiceControl_equalizer(voh, curItem); + else + LOG_ERR(L"Unhandled rackId: %08x", rackId); + + if (curItem->next == 0 || ret != Ok) break; + + curItem = (SceNgs2VoiceParamHead*)((uint64_t)curItem + curItem->next); + } - return Ok; + return ret; } EXPORT SYSV_ABI int32_t sceNgs2VoiceGetState(SceNgs2Handle* voh, SceNgs2VoiceState* state, size_t size) { + LOG_USE_MODULE(libSceNgs2); + + boost::unique_lock lock(MUTEX_INT); + if (voh == nullptr || state == nullptr) return getErr(ErrCode::_EINVAL); + + auto pimpl = getPimpl(); + if (auto it = pimpl->handles.find(voh); it == pimpl->handles.end()) return Err::Ngs2::INVALID_VOICE_HANDLE; if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; auto voice = (SceNgs2Handle_voice*)voh; - state->stateFlags = voice->state.stateFlags; + state->stateFlags = 0x20; // voice->state.data; + + LOG_DEBUG(L"state voice:0x%08llx state:%x", (uint64_t)voh, state->stateFlags); return Ok; } EXPORT SYSV_ABI int32_t sceNgs2VoiceGetStateFlags(SceNgs2Handle* voh, uint32_t* flags) { + LOG_USE_MODULE(libSceNgs2); + + boost::unique_lock lock(MUTEX_INT); if (voh == nullptr || flags == nullptr) return getErr(ErrCode::_EINVAL); + auto pimpl = getPimpl(); + if (auto it = pimpl->handles.find(voh); it == pimpl->handles.end()) return Err::Ngs2::INVALID_VOICE_HANDLE; if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; auto voice = (SceNgs2Handle_voice*)voh; - *flags = voice->state.stateFlags; + *flags = 0x20; // voice->state.data; + + LOG_DEBUG(L"state voice:0x%08llx state:%x", (uint64_t)voh, *flags); return Ok; } @@ -596,7 +703,7 @@ EXPORT SYSV_ABI int32_t sceNgs2GeomApply() { EXPORT SYSV_ABI int32_t sceNgs2GeomCalcListener() { LOG_USE_MODULE(libSceNgs2); - LOG_ERR(L"todo %S", __FUNCTION__); + LOG_TRACE(L"todo %S", __FUNCTION__); return Ok; } @@ -621,6 +728,13 @@ EXPORT SYSV_ABI int32_t sceNgs2RackDestroy(SceNgs2Handle* rh, SceNgs2ContextBuff auto freeHandler = rack->parent->alloc.freeHandler; int32_t ret = Ok; + + for (size_t n = 0; n < rack->options.maxVoices; ++n) { + getPimpl()->handles.erase(&rack->voices[n]); + rack->voices[n].~SceNgs2Handle_voice(); + } + + getPimpl()->handles.erase(rh); if (freeHandler != nullptr) { SceNgs2ContextBufferInfo cbi = { .hostBuffer = rack, @@ -639,6 +753,7 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemDestroy(SceNgs2Handle* sysh, SceNgs2Context boost::unique_lock lock(MUTEX_INT); auto system = (SceNgs2Handle_system*)sysh; + getPimpl()->handles.erase(system); auto freeHandler = system->alloc.freeHandler; diff --git a/modules/libSceNgs2/readFuncs.cpp b/modules/libSceNgs2/readFuncs.cpp index b389c9c4..a579ec32 100644 --- a/modules/libSceNgs2/readFuncs.cpp +++ b/modules/libSceNgs2/readFuncs.cpp @@ -4,10 +4,12 @@ #include "core/kernel/filesystem.h" #include "logging.h" extern "C" { +#include #include } #include #include + LOG_DEFINE_MODULE(libSceNgs2); namespace { @@ -50,9 +52,10 @@ int readFunc_linearBuffer(void* userData_, uint8_t* buf, int size) { if (readSize > 0) { userData->curOffset += readSize; ::memcpy(buf, userData->ptr, readSize); + return readSize; } - return readSize; + return -1; } int64_t seekFunc_linearBuffer(void* userData_, int64_t offset, int whence) { @@ -137,24 +140,31 @@ int32_t parseWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData astream = fmtctx->streams[stream_idx]; } + auto const totalSize = fmtctx->duration / (fmtctx->bit_rate / 8); + // Fill data wf->info.type = convWaveType(astream->codecpar->codec_id); wf->info.sampleRate = astream->codecpar->sample_rate; wf->info.channelsCount = convChanCount(astream->codecpar->ch_layout.nb_channels); // These are unknown for now - wf->loopBeginPos = wf->loopEndPos = 0; - - wf->samplesCount = astream->nb_frames; + wf->loopBeginPos = 0; + wf->loopEndPos = totalSize; - auto const totalSize = seekFunc(userData, 0, (int)SceWhence::end); + wf->samplesCount = (uint64_t)((fmtctx->duration / (float)AV_TIME_BASE) * (float)wf->info.sampleRate * (float)wf->info.channelsCount); wf->offset = 0; wf->size = totalSize; + wf->frameSize = astream->codecpar->frame_size; + wf->numframeSamples = astream->nb_frames; + wf->samplesDelay = 0; // todo + auto& block = wf->block[0]; block.offset = 0; block.size = totalSize; wf->numBlocks = 1; + + LOG_DEBUG(L"parse size:0x%08llx", totalSize); return Ok; } \ No newline at end of file diff --git a/modules/libSceNgs2/reader.cpp b/modules/libSceNgs2/reader.cpp index 295aa805..208e1a42 100644 --- a/modules/libSceNgs2/reader.cpp +++ b/modules/libSceNgs2/reader.cpp @@ -21,14 +21,19 @@ struct PImpl { userData_inerBuffer userData = {}; - AVStream* astream = nullptr; + int64_t numSamples = 0; + + // AVFormatContext* fmtctx = nullptr; + // AVStream* astream = nullptr; AVCodec const* codec = nullptr; int stream_idx = 0; AVCodecContext* codecContext = nullptr; - AVFrame* frame = nullptr; - SwrContext* swrCtx = nullptr; + AVFrame* frame = nullptr; + AVPacket* packet = nullptr; + + // SwrContext* swrCtx = nullptr; }; } // namespace @@ -40,88 +45,147 @@ Reader::~Reader() { delete (PImpl*)m_pimpl; } -bool Reader::init(void const* data, size_t size) { +bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { LOG_USE_MODULE(libSceNgs2); auto pimpl = (PImpl*)m_pimpl; - auto& cleanup = pimpl->cleanup; - auto& userData = pimpl->userData; + // Init Setup + // auto aBufferIo = (uint8_t*)av_malloc(4096 + AV_INPUT_BUFFER_PADDING_SIZE); - userData.ptr = data; - userData.size = size; - userData.curOffset = 0; + // AVIOContext* avioctx = avio_alloc_context(aBufferIo, 4096, 0, &userData, readFunc_linearBuffer, nullptr, seekFunc_linearBuffer); - // Init Setup - auto aBufferIo = (uint8_t*)av_malloc(4096 + AV_INPUT_BUFFER_PADDING_SIZE); + // cleanup.emplace_back([&] { av_free(avioctx); }); + // cleanup.emplace_back([&] { av_free(aBufferIo); }); - AVIOContext* avioctx = avio_alloc_context(aBufferIo, 4096, 0, &userData, readFunc_linearBuffer, nullptr, seekFunc_linearBuffer); + // // Open the input + // pimpl->fmtctx = avformat_alloc_context(); + // cleanup.emplace_back([&] { avformat_free_context(pimpl->fmtctx); }); - cleanup.emplace_back([&] { av_free(avioctx); }); - cleanup.emplace_back([&] { av_free(aBufferIo); }); + // pimpl->fmtctx->pb = avioctx; + // pimpl->fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; - // Open the input - AVFormatContext* fmtctx = avformat_alloc_context(); - cleanup.emplace_back([&] { avformat_free_context(fmtctx); }); + // int ret = avformat_open_input(&pimpl->fmtctx, "nullptr", nullptr, nullptr); + // if (ret != 0) { + // LOG_ERR(L"Reader: ffmpeg failed to read passed data: %d", ret); + // return false; + // } + // cleanup.emplace_back([&] { avformat_close_input(&pimpl->fmtctx); }); - fmtctx->pb = avioctx; - fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; + // pimpl->stream_idx = av_find_best_stream(pimpl->fmtctx, AVMEDIA_TYPE_AUDIO, -1, -1, &pimpl->codec, 0); - int ret = avformat_open_input(&fmtctx, "nullptr", nullptr, nullptr); - if (ret != 0) { - LOG_ERR(L"Reader: ffmpeg failed to read passed data: %d", ret); - return false; - } - cleanup.emplace_back([&] { avformat_close_input(&fmtctx); }); + // if (pimpl->stream_idx < 0) { + // LOG_ERR(L"Reader: no audio stream"); + // return false; + // } - pimpl->stream_idx = av_find_best_stream(fmtctx, AVMEDIA_TYPE_AUDIO, -1, -1, &pimpl->codec, 0); + // pimpl->astream = pimpl->fmtctx->streams[pimpl->stream_idx]; - if (pimpl->stream_idx < 0) { - LOG_ERR(L"Reader: no audio stream"); - return false; - } + // pimpl->codecContext = avcodec_alloc_context3(pimpl->codec); + // if (auto err = avcodec_parameters_to_context(pimpl->codecContext, pimpl->astream->codecpar); err != 0) { + // LOG_ERR(L"Reader: avcodec_parameters_to_context err:%d", err); + // return false; + // } + // cleanup.emplace_back([&] { avcodec_free_context(&pimpl->codecContext); }); - pimpl->astream = fmtctx->streams[pimpl->stream_idx]; + // // Setup multithreading + // if (pimpl->codec->capabilities | AV_CODEC_CAP_FRAME_THREADS) + // pimpl->codecContext->thread_type = FF_THREAD_FRAME; + // else if (pimpl->codec->capabilities | AV_CODEC_CAP_SLICE_THREADS) + // pimpl->codecContext->thread_type = FF_THREAD_SLICE; + // else + // pimpl->codecContext->thread_count = 1; // don't use multithreading + // // - - pimpl->codecContext = avcodec_alloc_context3(pimpl->codec); - if (auto err = avcodec_parameters_to_context(pimpl->codecContext, pimpl->astream->codecpar); err != 0) { - LOG_ERR(L"Reader: avcodec_parameters_to_context err:%d", err); - return false; - } - cleanup.emplace_back([&] { avcodec_free_context(&pimpl->codecContext); }); - - // Setup multithreading - if (pimpl->codec->capabilities | AV_CODEC_CAP_FRAME_THREADS) - pimpl->codecContext->thread_type = FF_THREAD_FRAME; - else if (pimpl->codec->capabilities | AV_CODEC_CAP_SLICE_THREADS) - pimpl->codecContext->thread_type = FF_THREAD_SLICE; - else - pimpl->codecContext->thread_count = 1; // don't use multithreading - // - - - if (auto err = avcodec_open2(pimpl->codecContext, pimpl->codec, NULL); err < 0) { - LOG_ERR(L"Reader: avcodec_open2 err:%d", err); - return false; - } + // if (auto err = avcodec_open2(pimpl->codecContext, pimpl->codec, NULL); err < 0) { + // LOG_ERR(L"Reader: avcodec_open2 err:%d", err); + // return false; + // } - if (swr_alloc_set_opts2(&pimpl->swrCtx, &pimpl->codecContext->ch_layout, AVSampleFormat::AV_SAMPLE_FMT_S16, pimpl->codecContext->sample_rate, - &pimpl->codecContext->ch_layout, pimpl->codecContext->sample_fmt, pimpl->codecContext->sample_rate, 0, NULL)) { - LOG_ERR(L"Reader:Couldn't alloc swr"); - return false; - } + // if (swr_alloc_set_opts2(&pimpl->swrCtx, &pimpl->codecContext->ch_layout, AVSampleFormat::AV_SAMPLE_FMT_S16, pimpl->codecContext->sample_rate, + // &pimpl->codecContext->ch_layout, pimpl->codecContext->sample_fmt, pimpl->codecContext->sample_rate, 0, NULL)) { + // LOG_ERR(L"Reader:Couldn't alloc swr"); + // return false; + // } + + // swr_init(pimpl->swrCtx); + // cleanup.emplace_back([&] { swr_free(&pimpl->swrCtx); }); - swr_init(pimpl->swrCtx); - cleanup.emplace_back([&] { swr_free(&pimpl->swrCtx); }); + // pimpl->frame = av_frame_alloc(); + // cleanup.emplace_back([&] { av_frame_free(&pimpl->frame); }); - pimpl->frame = av_frame_alloc(); - cleanup.emplace_back([&] { av_frame_free(&pimpl->frame); }); + // pimpl->packet = av_packet_alloc(); + // cleanup.emplace_back([&] { av_packet_free(&pimpl->packet); }); m_isInit = true; return true; } -bool Reader::getAudio(void* buffer, size_t bufferSize) { +bool Reader::getAudio(SceNgs2Handle_voice* handle, void* buffer, size_t bufferSize) { + if (m_isInit == false || !handle->state.bits.Playing || (handle->state.bits.Playing && handle->state.bits.Paused)) { + std::memset(buffer, 0, bufferSize); + return true; + } + LOG_USE_MODULE(libSceNgs2); + + auto pimpl = (PImpl*)m_pimpl; + std::memset(buffer, 0, bufferSize); + + // size_t offset = 0; + + // int const outNumSamples = swr_get_out_samples(pimpl->swrCtx, pimpl->frame->nb_samples); + // auto const bufferSize_ = pimpl->frame->ch_layout.nb_channels * outNumSamples * av_get_bytes_per_sample((AVSampleFormat)pimpl->frame->format); + + // while (offset < bufferSize) { + // // Get a new packet + // if (pimpl->packet == nullptr) { + // int state = av_read_frame(pimpl->fmtctx, pimpl->packet); + // if (state < 0) { + // if (state != AVERROR_EOF) { + // LOG_ERR(L"av_read_frame error %d", state); + // } else { + // handle->state.bits.Empty = true; + // handle->state.bits.Playing = false; + // } + // std::memset(buffer, 0, bufferSize); + // return false; + // } + // } + // // - + + // // Process packet + // if (int ret = avcodec_send_packet(pimpl->codecContext, pimpl->packet); ret < 0) { + // if (ret == AVERROR(EAGAIN)) { + // av_packet_unref(pimpl->packet); + // pimpl->packet = nullptr; + // continue; // Get new frame + // } else if (ret == AVERROR_EOF) { + // handle->state.bits.Empty = true; + // } else { + // handle->state.bits.Error = true; + // } + // handle->state.bits.Playing = false; + // std::memset(buffer, 0, bufferSize); + // return false; + // } + + // av_packet_unref(pimpl->packet); + // //- packet + + // // Now the frames + // auto const retRecv = avcodec_receive_frame(pimpl->codecContext, pimpl->frame); + + // uint8_t* audioBuffers[1] = {(uint8_t*)buffer + offset}; + // if (swr_convert(pimpl->swrCtx, audioBuffers, outNumSamples, (uint8_t const**)pimpl->frame->extended_data, pimpl->frame->nb_samples) < 0) { + // LOG_WARN(L"swr_convert"); + // } + + // av_frame_unref(pimpl->frame); + // // - + + // offset += bufferSize_; + // } return true; } \ No newline at end of file diff --git a/modules/libSceNgs2/reader.h b/modules/libSceNgs2/reader.h index 7e0dc174..98416361 100644 --- a/modules/libSceNgs2/reader.h +++ b/modules/libSceNgs2/reader.h @@ -1,5 +1,8 @@ #pragma once +struct SceNgs2Handle_voice; +struct SceNgs2SamplerVoiceWaveformBlocksParam; + class Reader { void* m_pimpl; bool m_isInit = false; @@ -8,7 +11,7 @@ class Reader { Reader(); ~Reader(); - bool init(void const* data, size_t size); + bool init(SceNgs2SamplerVoiceWaveformBlocksParam const* param); - bool getAudio(void* buffer, size_t bufferSize); + bool getAudio(SceNgs2Handle_voice* handle, void* buffer, size_t bufferSize); }; \ No newline at end of file diff --git a/modules/libSceNgs2/types.h b/modules/libSceNgs2/types.h index ecbe3490..712cc018 100644 --- a/modules/libSceNgs2/types.h +++ b/modules/libSceNgs2/types.h @@ -9,16 +9,16 @@ union SceNgs2VoiceStateFlags { uint32_t data; struct { - bool Inuse : 1; - bool Playing : 1; - bool Paused : 1; - bool Stopped : 1; - bool Error : 1; - bool Empty : 1; + bool Inuse : 1 = false; + bool Playing : 1 = false; + bool Paused : 1 = false; + bool Stopped : 1 = false; + bool Error : 1 = false; + bool Empty : 1 = true; } bits; }; -enum class SceNgs2VoiceEvent { +enum class SceNgs2VoiceEvent : uint32_t { Play, Stop, Stop_imm, @@ -113,6 +113,17 @@ enum class SceNgs2SubmixerParam : uint16_t { SET_FILTER, }; +#pragma pack(push, 1) + +struct SceNgs2WaveformInfo { + SceNgs2WaveFormType type; + SceNgs2ChannelsCount channelsCount; + uint32_t sampleRate; + uint32_t configData; + uint32_t frameOffset; + uint32_t frameMargin; +}; + class Reader; struct SceNgs2VoiceHandle { @@ -183,15 +194,12 @@ struct SceNgs2RackOption { char name[SCE_NGS2_RACK_NAME_LENGTH] = "\0"; uint32_t flags; - uint32_t maxGrainSamples = 1; - uint32_t maxVoices = 1; - ; + uint32_t maxGrainSamples = 1; + uint32_t maxVoices = 1; uint32_t maxInputDelayBlocks = 1; - ; - uint32_t maxMatrices = 1; - ; - uint32_t maxPorts = 1; - ; + uint32_t maxMatrices = 1; + uint32_t maxPorts = 1; + uint32_t aReserved[20]; }; @@ -205,6 +213,7 @@ struct SceNgs2Handle_rack; struct SceNgs2Handle { SceNgs2HandleType const type; + SceNgs2WaveformInfo info; SceNgs2Handle(SceNgs2HandleType type): type(type) {} @@ -218,6 +227,8 @@ struct SceNgs2Handle_system: public SceNgs2Handle { SceNgs2Handle_rack* mastering = nullptr; SceNgs2Handle_rack* sampler = nullptr; SceNgs2Handle_rack* submixer = nullptr; + SceNgs2Handle_rack* reverb = nullptr; + SceNgs2Handle_rack* equalizer = nullptr; // - @@ -230,13 +241,16 @@ struct SceNgs2Handle_system: public SceNgs2Handle { struct SceNgs2Handle_voice: public SceNgs2Handle { SceNgs2Handle_rack* parent; - SceNgs2VoiceState state {}; + + SceNgs2VoiceStateFlags state {}; Reader* reader = nullptr; // optional, depends on racktype SceNgs2Handle_voice(SceNgs2Handle_rack* parent): SceNgs2Handle(SceNgs2HandleType::Voice), parent(parent) {} virtual ~SceNgs2Handle_voice(); + + void ev_KickEvent(SceNgs2VoiceEvent id); }; struct SceNgs2Handle_rack: public SceNgs2Handle { @@ -249,7 +263,7 @@ struct SceNgs2Handle_rack: public SceNgs2Handle { SceNgs2Handle_rack(SceNgs2Handle_system* parent, SceNgs2RackOption const* options_, uint32_t rackId) : SceNgs2Handle(SceNgs2HandleType::Rack), rackId(rackId), parent(parent) { - if (options_ != nullptr) memcpy(&options, &options_, sizeof(SceNgs2RackOption)); + if (options_ != nullptr) memcpy(&options, options_, sizeof(SceNgs2RackOption)); } virtual ~SceNgs2Handle_rack() = default; @@ -262,21 +276,12 @@ struct SceNgs2RenderBufferInfo { SceNgs2ChannelsCount channelsCount; }; -struct SceNgs2WaveformInfo { - SceNgs2WaveFormType type; - SceNgs2ChannelsCount channelsCount; - uint32_t sampleRate; - uint32_t configData; - uint32_t frameOffset; - uint32_t frameMargin; -}; - struct SceNgs2WaveformBlock { uint32_t offset; uint32_t size; - uint32_t : 32; - uint32_t : 32; - uint32_t : 32; + uint32_t numRepeat; + uint32_t skipSamples; + uint32_t numSamples; uint32_t : 32; uintptr_t userData; }; @@ -290,10 +295,11 @@ struct SceNgs2WaveformFormat { uint32_t samplesCount; uint32_t : 32; uint32_t : 32; - uint32_t : 32; - uint32_t : 32; - uint32_t : 32; - uint32_t : 32; + uint32_t dataPerFrame; + uint32_t frameSize; + uint32_t numframeSamples; + uint32_t samplesDelay; + uint32_t numBlocks; SceNgs2WaveformBlock block[4]; }; @@ -376,6 +382,13 @@ struct SceNgs2SamplerVoiceWaveformBlocksParam { const SceNgs2WaveformBlock* aBlock; }; +struct SceNgs2SamplerVoiceSetupParam { + SceNgs2VoiceParamHead header; + SceNgs2WaveformInfo format; + uint32_t flags; + uint32_t reserved; +}; + struct SceNgs2VoiceCallbackInfo { uintptr_t callbackData; SceNgs2Handle* voiceHandle; @@ -440,3 +453,5 @@ struct SceNgs2PanParam { float fbwLevel; float lfeLevel; }; + +#pragma pack(pop) \ No newline at end of file diff --git a/modules/libSceNpParty/entry.cpp b/modules/libSceNpParty/entry.cpp index f6d25b78..cb09c62d 100644 --- a/modules/libSceNpParty/entry.cpp +++ b/modules/libSceNpParty/entry.cpp @@ -17,7 +17,7 @@ EXPORT SYSV_ABI int32_t sceNpPartyInitialize() { EXPORT SYSV_ABI int32_t sceNpPartyCheckCallback() { LOG_USE_MODULE(libSceNpParty); - LOG_ERR(L"todo %S", __FUNCTION__); + LOG_TRACE(L"todo %S", __FUNCTION__); return Ok; } From 894a75ad6baf425cf2379bca0252a8d88d34c4e7 Mon Sep 17 00:00:00 2001 From: Martin Baliet Date: Wed, 8 May 2024 14:19:07 +0200 Subject: [PATCH 06/19] ngs2| dump --- modules/libSceAudioOut/entry.cpp | 14 +- modules/libSceNgs2/entry.cpp | 88 ++++----- modules/libSceNgs2/readFuncs.cpp | 139 ++++++++------ modules/libSceNgs2/readFuncs.h | 2 +- modules/libSceNgs2/reader.cpp | 316 +++++++++++++++++++------------ modules/libSceNgs2/reader.h | 12 +- modules/libSceNgs2/riffTypes.h | 24 +++ modules/libSceNgs2/types.h | 6 +- 8 files changed, 356 insertions(+), 245 deletions(-) create mode 100644 modules/libSceNgs2/riffTypes.h diff --git a/modules/libSceAudioOut/entry.cpp b/modules/libSceAudioOut/entry.cpp index b30a9bbc..ce159c17 100644 --- a/modules/libSceAudioOut/entry.cpp +++ b/modules/libSceAudioOut/entry.cpp @@ -20,7 +20,7 @@ struct PortOut { SceAudioOutPortType type = SceAudioOutPortType::MAIN; uint8_t sampleSize = 0; uint32_t samplesNum = 0; - uint32_t freq = 0; + uint32_t sampleRate = 0; uint32_t queued = 0; SceAudioOutParamFormat format = SceAudioOutParamFormat::FLOAT_MONO; uint64_t lastOutputTime = 0; @@ -71,7 +71,7 @@ class PortsOut { if (port.deviceName.compare(0, std::string::npos, devName, 0, port.deviceName.length()) != 0) continue; SDL_AudioSpec fmt { - .freq = static_cast(port.freq), + .freq = static_cast(port.sampleRate), .format = port.sdlFormat, .channels = static_cast(port.channelsNum), .samples = static_cast(port.samplesNum), @@ -167,7 +167,7 @@ void syncPort(PortOut* port) { const uint32_t bytesize = bytesize_1ch * port->channelsNum; if (port->device == 0) { - float duration = bytesize_1ch / float(port->freq * port->sampleSize); + float duration = bytesize_1ch / float(port->sampleRate * port->sampleSize); SDL_Delay(int(duration * 1000)); // Pretending that we playing something return; } @@ -237,7 +237,7 @@ EXPORT SYSV_ABI int32_t sceAudioOutInit(void) { return Err::AudioOut::OUT_OF_MEMORY; } -EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type, int32_t index, uint32_t len, uint32_t freq, uint32_t param) { +EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type, int32_t index, uint32_t numSamples, uint32_t sampleRate, uint32_t param) { LOG_USE_MODULE(libSceAudioOut); LOG_TRACE(L"%S", __FUNCTION__); auto pimpl = getData(); @@ -259,8 +259,8 @@ EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type int handle; if (auto port = pimpl->portsOut.AcquirePort(type, &handle)) { port->userId = userId; - port->samplesNum = len; - port->freq = freq; + port->samplesNum = numSamples; + port->sampleRate = sampleRate; port->format = SceAudioOutParamFormat(param & 0x0000007F); if ((param & 0x000F0000) != 0) { @@ -375,7 +375,7 @@ EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type } SDL_AudioSpec fmt { - .freq = static_cast(freq), + .freq = static_cast(sampleRate), .format = port->sdlFormat, .channels = static_cast(port->channelsNum), .samples = static_cast(port->samplesNum), diff --git a/modules/libSceNgs2/entry.cpp b/modules/libSceNgs2/entry.cpp index ffce1b15..9b7cc5e4 100644 --- a/modules/libSceNgs2/entry.cpp +++ b/modules/libSceNgs2/entry.cpp @@ -27,23 +27,26 @@ int32_t _voiceControlWaveformBlock(SceNgs2Handle* voh, const SceNgs2SamplerVoice LOG_USE_MODULE(libSceNgs2); LOG_TRACE(L"waveblock: %d\n", svwfbp->numBlocks); - LOG_TRACE(L"waveptr: %llx\n", svwfbp->data); + LOG_DEBUG(L"waveptr: %llx\n", svwfbp->data); if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; auto voice = (SceNgs2Handle_voice*)voh; - voice->reader = std::make_unique().release(); + if (voice->reader == nullptr) voice->reader = std::make_unique(voice).release(); + + // svwfbp->data can be nullptr! if (!voice->reader->init(svwfbp)) { return Err::Ngs2::INVALID_WAVEFORM_DATA; } - voice->state.bits.Empty = false; - LOG_DEBUG(L"waveptr voice:0x%08llx %llx", (uint64_t)voh, svwfbp->data); return Ok; } int32_t voiceControl_voice(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + LOG_USE_MODULE(libSceNgs2); + LOG_INFO(L"voiceControl_voice id:%u type:%u", phead->id & 0xFFFF, voh->type); + if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; auto voice = (SceNgs2Handle_voice*)voh; @@ -51,12 +54,15 @@ int32_t voiceControl_voice(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phea case SceNgs2VoiceParam::SET_MATRIX_LEVELS: { } break; case SceNgs2VoiceParam::SET_PORT_VOLUME: { + // todo } break; case SceNgs2VoiceParam::SET_PORT_MATRIX: { } break; case SceNgs2VoiceParam::SET_PORT_DELAY: { } break; case SceNgs2VoiceParam::PATCH: { + auto item = (SceNgs2VoicePatchParam*)phead; + // todo } break; case SceNgs2VoiceParam::KICK_EVENT: { auto item = (SceNgs2VoiceEventParam*)phead; @@ -69,6 +75,9 @@ int32_t voiceControl_voice(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phea } int32_t voiceControl_mastering(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + LOG_USE_MODULE(libSceNgs2); + LOG_INFO(L"voiceControl_mastering id:%u type:%u", phead->id & 0xFFFF, voh->type); + switch ((SceNgs2MasteringParam)(phead->id & 0xFFFF)) { case SceNgs2MasteringParam::SETUP: { } break; @@ -131,6 +140,7 @@ int32_t voiceControl_sampler(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* ph case SceNgs2SamplerParam::SET_FILTER: { } break; } + return Ok; } @@ -198,7 +208,7 @@ EXPORT SYSV_ABI int32_t sceNgs2RackQueryBufferSize(uint32_t rackId, const SceNgs if (ro != nullptr && ro->size < sizeof(SceNgs2RackOption)) return Err::Ngs2::INVALID_OPTION_SIZE; auto const numVoices = ro != nullptr ? ro->maxVoices : SceNgs2RackOption().maxVoices; - cbi->hostBufferSize = sizeof(SceNgs2Handle_rack) + (numVoices * sizeof(SceNgs2Handle_voice)); + cbi->hostBufferSize = sizeof(SceNgs2Handle_rack); return Ok; } @@ -266,18 +276,6 @@ EXPORT SYSV_ABI int32_t sceNgs2RackCreate(SceNgs2Handle* sysh, uint32_t rackId, auto rack = (SceNgs2Handle_rack*)(*outh); - // Init voices - { - auto addrVoices = (uint64_t)rack + sizeof(SceNgs2Handle_rack); // At end of rack struct - - rack->voices = (SceNgs2Handle_voice*)addrVoices; - - for (uint16_t n = 0; n < rack->options.maxVoices; ++n, addrVoices += sizeof(SceNgs2Handle_voice)) { - auto pVoice = new ((void*)addrVoices) SceNgs2Handle_voice(rack); - } - } - // - - // Add to system if (rackId == SCE_NGS2_RACK_ID_MASTERING || rackId == SCE_NGS2_RACK_ID_CUSTOM_MASTERING) { system->mastering = rack; @@ -307,11 +305,9 @@ EXPORT SYSV_ABI int32_t sceNgs2RackCreateWithAllocator(SceNgs2Handle* sysh, uint auto system = (SceNgs2Handle_system*)sysh; - auto const numVoices = ro != nullptr ? ro->maxVoices : SceNgs2RackOption().maxVoices; - SceNgs2ContextBufferInfo cbi = { .hostBuffer = nullptr, - .hostBufferSize = sizeof(SceNgs2Handle_rack) + (numVoices * sizeof(SceNgs2Handle_voice)), + .hostBufferSize = sizeof(SceNgs2Handle_rack), .userData = alloc->userData, }; @@ -324,17 +320,6 @@ EXPORT SYSV_ABI int32_t sceNgs2RackCreateWithAllocator(SceNgs2Handle* sysh, uint getPimpl()->handles.emplace(*outh); auto rack = (SceNgs2Handle_rack*)(*outh); - // Init voices - { - auto addrVoices = (uint64_t)rack + sizeof(SceNgs2Handle_rack); // At end of rack struct - - rack->voices = (SceNgs2Handle_voice*)addrVoices; - - for (uint16_t n = 0; n < numVoices; ++n, addrVoices += sizeof(SceNgs2Handle_voice)) { - auto pVoice = new ((void*)addrVoices) SceNgs2Handle_voice(rack); - } - } - // - // Add to system if (rackId == SCE_NGS2_RACK_ID_MASTERING || rackId == SCE_NGS2_RACK_ID_CUSTOM_MASTERING) { @@ -399,7 +384,7 @@ EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformData(const void* ptr, size_t size, S boost::unique_lock lock(MUTEX_INT); userData_inerBuffer userData {ptr, size, 0}; - return parseWave(readFunc_linearBuffer, seekFunc_linearBuffer, &userData, wf); + return parseRiffWave(readFunc_linearBuffer, seekFunc_linearBuffer, &userData, wf); } /** @@ -422,7 +407,7 @@ EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformFile(const char* path, long offset, if (fileHandle < 0) return Err::Ngs2::INVALID_WAVEFORM_DATA; if (offset != 0) filesystem::lseek(fileHandle, offset, (int)SceWhence::beg); - return parseWave(readFunc_file, seekFunc_file, reinterpret_cast(fileHandle), wf); + return parseRiffWave(readFunc_file, seekFunc_file, reinterpret_cast(fileHandle), wf); } /** @@ -441,7 +426,7 @@ EXPORT SYSV_ABI int32_t sceNgs2ParseWaveformUser(SceWaveformUserFunc func, uintp boost::unique_lock lock(MUTEX_INT); userData_user userData {func, userData_, 0}; - return parseWave(readFunc_user, seekFunc_user, (void*)&userData, wf); + return parseRiffWave(readFunc_user, seekFunc_user, (void*)&userData, wf); } // - wave parsing @@ -501,9 +486,9 @@ EXPORT SYSV_ABI int32_t sceNgs2RackGetVoiceHandle(SceNgs2Handle* rh, uint32_t vo auto rack = (SceNgs2Handle_rack*)rh; if (voiceId > rack->options.maxVoices) return Err::Ngs2::INVALID_VOICE_INDEX; - *outh = (SceNgs2Handle*)((uint64_t)rack->voices + voiceId * sizeof(SceNgs2Handle_voice)); - getPimpl()->handles.emplace(*outh); + *outh = &rack->voices.emplace(std::make_pair(voiceId, rack)).first->second; + getPimpl()->handles.emplace(*outh); LOG_DEBUG(L"-> GetVoiceHandle: rack:0x%08llx id:%u @0x%08llx", (uint64_t)rh, voiceId, (uint64_t)*outh); return Ok; } @@ -562,10 +547,8 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemUnlock(SceNgs2Handle* sysh) { } EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBufferInfo* rbi, int32_t count) { - LOG_USE_MODULE(libSceNgs2); - LOG_TRACE(L"todo %S", __FUNCTION__); - - auto system = (SceNgs2Handle_system*)sysh; + boost::unique_lock lock(MUTEX_INT); + auto system = (SceNgs2Handle_system*)sysh; if (system == nullptr) return Err::Ngs2::INVALID_SYSTEM_HANDLE; if (rbi->bufferPtr == nullptr) return Err::Ngs2::INVALID_BUFFER_ADDRESS; if (rbi->bufferSize == 0) return Err::Ngs2::INVALID_BUFFER_SIZE; @@ -583,11 +566,11 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBu } else { for (int32_t i = 0; i < count; i++) { if (rbi[i].bufferPtr != nullptr) { - auto& samplerVoice = system->sampler->voices[0]; - if (samplerVoice.reader != nullptr) { - samplerVoice.reader->getAudio(&samplerVoice, rbi[i].bufferPtr, rbi[i].bufferSize); - } else { - std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); + std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); + for (auto& voice: system->sampler->voices) { + if (voice.second.reader != nullptr) { + voice.second.reader->getAudio(rbi[i].bufferPtr, rbi[i].bufferSize); + } } } } @@ -672,9 +655,9 @@ EXPORT SYSV_ABI int32_t sceNgs2VoiceGetState(SceNgs2Handle* voh, SceNgs2VoiceSta if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; auto voice = (SceNgs2Handle_voice*)voh; - state->stateFlags = 0x20; // voice->state.data; + state->stateFlags = voice->state.data; - LOG_DEBUG(L"state voice:0x%08llx state:%x", (uint64_t)voh, state->stateFlags); + // LOG_DEBUG(L"state voice:0x%08llx state:%x", (uint64_t)voh, state->stateFlags); return Ok; } @@ -689,9 +672,9 @@ EXPORT SYSV_ABI int32_t sceNgs2VoiceGetStateFlags(SceNgs2Handle* voh, uint32_t* if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; auto voice = (SceNgs2Handle_voice*)voh; - *flags = 0x20; // voice->state.data; + *flags = voice->state.data; - LOG_DEBUG(L"state voice:0x%08llx state:%x", (uint64_t)voh, *flags); + // LOG_DEBUG(L"state voice:0x%08llx state:%x", (uint64_t)voh, *flags); return Ok; } @@ -729,16 +712,15 @@ EXPORT SYSV_ABI int32_t sceNgs2RackDestroy(SceNgs2Handle* rh, SceNgs2ContextBuff int32_t ret = Ok; - for (size_t n = 0; n < rack->options.maxVoices; ++n) { - getPimpl()->handles.erase(&rack->voices[n]); - rack->voices[n].~SceNgs2Handle_voice(); + for (auto voice: rack->voices) { + getPimpl()->handles.erase(&voice.second); } getPimpl()->handles.erase(rh); if (freeHandler != nullptr) { SceNgs2ContextBufferInfo cbi = { .hostBuffer = rack, - .hostBufferSize = sizeof(SceNgs2Handle_rack) + (rack->options.maxVoices * sizeof(SceNgs2Handle_voice)), + .hostBufferSize = sizeof(SceNgs2Handle_rack), }; rack->~SceNgs2Handle_rack(); ret = freeHandler(&cbi); diff --git a/modules/libSceNgs2/readFuncs.cpp b/modules/libSceNgs2/readFuncs.cpp index a579ec32..f7a52843 100644 --- a/modules/libSceNgs2/readFuncs.cpp +++ b/modules/libSceNgs2/readFuncs.cpp @@ -3,12 +3,14 @@ #include "core/fileManager/ifile.h" #include "core/kernel/filesystem.h" #include "logging.h" +#include "riffTypes.h" extern "C" { #include #include } #include #include +#include LOG_DEFINE_MODULE(libSceNgs2); @@ -46,30 +48,37 @@ static SceNgs2WaveFormType convWaveType(AVCodecID codec) { int readFunc_linearBuffer(void* userData_, uint8_t* buf, int size) { auto userData = (userData_inerBuffer*)userData_; - int const dataLeft = userData->size - userData->curOffset; - auto readSize = std::min(dataLeft, size); + int64_t const dataLeft = (int64_t)userData->size - (int64_t)userData->curOffset; + + auto readSize = std::min(dataLeft, (int64_t)size); if (readSize > 0) { + ::memcpy(buf, (uint8_t*)userData->ptr + userData->curOffset, readSize); userData->curOffset += readSize; - ::memcpy(buf, userData->ptr, readSize); return readSize; } + userData->curOffset = 0; // reset it return -1; } int64_t seekFunc_linearBuffer(void* userData_, int64_t offset, int whence) { auto userData = (userData_inerBuffer*)userData_; - switch ((SceWhence)whence) { - case SceWhence::beg: userData->curOffset = offset; break; - case SceWhence::cur: + if ((whence & AVSEEK_SIZE) > 0) { + // return size (0 on not avail) + return userData->size; + } + + switch ((std::ios_base::seekdir)(whence & 0xff)) { + case std::ios_base::beg: userData->curOffset = offset; break; + case std::ios_base::cur: if (userData->curOffset < offset) userData->curOffset = 0; else userData->curOffset += offset; break; - case SceWhence::end: userData->curOffset = std::min(userData->size, userData->size + offset); break; + case std::ios_base::end: userData->curOffset = std::min(userData->size, userData->size + offset); break; } return userData->curOffset; @@ -99,72 +108,88 @@ int64_t seekFunc_user(void* userData_, int64_t offset, int whence) { return 0; // undefined } -int32_t parseWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData, SceNgs2WaveformFormat* wf) { +int32_t parseRiffWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData, SceNgs2WaveformFormat* wf) { LOG_USE_MODULE(libSceNgs2); - std::list> cleanup; - - // Setup - auto aBufferIo = (uint8_t*)av_malloc(4096 + AV_INPUT_BUFFER_PADDING_SIZE); - - AVIOContext* avioctx = avio_alloc_context(aBufferIo, 4096, 0, userData, readFunc, nullptr, seekFunc); + // Load headers and check magic - cleanup.emplace_back([&] { av_free(avioctx); }); - cleanup.emplace_back([&] { av_free(aBufferIo); }); - - // Open the input - AVFormatContext* fmtctx = avformat_alloc_context(); - cleanup.emplace_back([&] { avformat_free_context(fmtctx); }); - - fmtctx->pb = avioctx; - fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; - - int ret = avformat_open_input(&fmtctx, "nullptr", nullptr, nullptr); - if (ret != 0) { - LOG_ERR(L"ParseRIFF: ffmpeg failed to read passed data: %d", ret); + // Check if correct file + RiffWaveHeader riffHeader; + readFunc(userData, (uint8_t*)&riffHeader, sizeof(RiffWaveHeader)); + if (memcmp(riffHeader.chunkID, "RIFF", 4) != 0 || memcmp(riffHeader.riffType, "WAVE", 4) != 0) { + LOG_ERR(L"wrong riff 0x%lx 0x%lx", riffHeader.chunkID, riffHeader.riffType); return Err::Ngs2::FAIL; } - cleanup.emplace_back([&] { avformat_close_input(&fmtctx); }); - - AVStream* astream = nullptr; - AVCodec const* codec = nullptr; + // - - { - auto stream_idx = av_find_best_stream(fmtctx, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0); + // Format header + RiffFormatHeader formatHeader; + readFunc(userData, (uint8_t*)&formatHeader, sizeof(RiffFormatHeader)); - if (stream_idx < 0) { - LOG_ERR(L"ParseRIFF: no audio stream"); - return Err::Ngs2::FAIL; - } + if (memcmp(formatHeader.chunkID, "fmt ", 4) != 0) { + return Err::Ngs2::FAIL; + } - astream = fmtctx->streams[stream_idx]; + if ((8 + formatHeader.chunkSize) > sizeof(RiffFormatHeader)) { + std::vector extraFmt(8 + formatHeader.chunkSize - sizeof(RiffFormatHeader)); + readFunc(userData, extraFmt.data(), extraFmt.size()); } + // - - auto const totalSize = fmtctx->duration / (fmtctx->bit_rate / 8); + // parse rest + uint32_t offset = sizeof(RiffWaveHeader) + 8 + formatHeader.chunkSize; - // Fill data - wf->info.type = convWaveType(astream->codecpar->codec_id); - wf->info.sampleRate = astream->codecpar->sample_rate; - wf->info.channelsCount = convChanCount(astream->codecpar->ch_layout.nb_channels); + uint32_t dataSize = 0; + uint32_t numOfSamples = 1; - // These are unknown for now - wf->loopBeginPos = 0; - wf->loopEndPos = totalSize; + // Data header + while (offset < riffHeader.chunkSize) { + RiffHeader header; + readFunc(userData, (uint8_t*)&header, sizeof(RiffHeader)); - wf->samplesCount = (uint64_t)((fmtctx->duration / (float)AV_TIME_BASE) * (float)wf->info.sampleRate * (float)wf->info.channelsCount); + auto readBytes = sizeof(RiffHeader); + if (memcmp(header.chunkID, "fact", 4) == 0) { + readFunc(userData, (uint8_t*)&numOfSamples, 4); + readBytes += 4; + } else if (memcmp(header.chunkID, "data", 4) == 0) { + dataSize = header.chunkSize; + break; + } // Dump read data - wf->offset = 0; - wf->size = totalSize; + if ((8 + header.chunkSize) > readBytes) { + std::vector extra(8 + header.chunkSize - readBytes); + readFunc(userData, extra.data(), extra.size()); + } + // - - wf->frameSize = astream->codecpar->frame_size; - wf->numframeSamples = astream->nb_frames; - wf->samplesDelay = 0; // todo + offset += 8 + header.chunkSize; + } + if (dataSize == 0) return Err::Ngs2::FAIL; - auto& block = wf->block[0]; - block.offset = 0; - block.size = totalSize; - wf->numBlocks = 1; + // Fill data + wf->info.type = (SceNgs2WaveFormType)formatHeader.audioFormat; + wf->info.channelsCount = (SceNgs2ChannelsCount)formatHeader.numChannels; + wf->info.sampleRate = formatHeader.sampleRate; + wf->info.frameOffset = formatHeader.frameSize; + wf->info.frameMargin = 0; // todo + + wf->offset = offset; + wf->size = dataSize; + wf->loopBeginPos = 0; // todo + wf->loopEndPos = 0; // todo + wf->samplesCount = 1; // todo + wf->dataPerFrame = 1; // todo + wf->frameSize = formatHeader.frameSize; // todo + wf->numframeSamples = 1; // todo + wf->samplesDelay = 0; // todo + + auto& block = wf->block[0]; + block.offset = wf->offset; + block.size = dataSize; + block.numRepeat = 1; + block.skipSamples = 1; + block.numSamples = numOfSamples; + wf->numBlocks = 1; - LOG_DEBUG(L"parse size:0x%08llx", totalSize); return Ok; } \ No newline at end of file diff --git a/modules/libSceNgs2/readFuncs.h b/modules/libSceNgs2/readFuncs.h index 918b4115..1aeed42c 100644 --- a/modules/libSceNgs2/readFuncs.h +++ b/modules/libSceNgs2/readFuncs.h @@ -23,4 +23,4 @@ int64_t seekFunc_file(void* userData_, int64_t offset, int whence); int readFunc_user(void* userData_, uint8_t* buf, int size); int64_t seekFunc_user(void* userData_, int64_t offset, int whence); -int32_t parseWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData, SceNgs2WaveformFormat* wf); \ No newline at end of file +int32_t parseRiffWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData, SceNgs2WaveformFormat* wf); \ No newline at end of file diff --git a/modules/libSceNgs2/reader.cpp b/modules/libSceNgs2/reader.cpp index 208e1a42..5e90bb2f 100644 --- a/modules/libSceNgs2/reader.cpp +++ b/modules/libSceNgs2/reader.cpp @@ -8,6 +8,7 @@ extern "C" { #include "logging.h" #include "readFuncs.h" +#include "riffTypes.h" #include "types.h" #include @@ -19,25 +20,28 @@ namespace { struct PImpl { std::list> cleanup; - userData_inerBuffer userData = {}; + uint8_t const* data = nullptr; + SceNgs2WaveformBlock block; - int64_t numSamples = 0; + uint32_t curOffset = 0; - // AVFormatContext* fmtctx = nullptr; - // AVStream* astream = nullptr; - AVCodec const* codec = nullptr; - int stream_idx = 0; + userData_inerBuffer userData = {}; + AVFormatContext* fmtctx = nullptr; + AVStream* astream = nullptr; + AVCodec const* codec = nullptr; + int stream_idx = 0; AVCodecContext* codecContext = nullptr; - AVFrame* frame = nullptr; - AVPacket* packet = nullptr; + AVFrame* frame = nullptr; + AVPacket* packet = nullptr; + bool newPacket = true; - // SwrContext* swrCtx = nullptr; + SwrContext* swrCtx = nullptr; }; } // namespace -Reader::Reader() { +Reader::Reader(SceNgs2Handle_voice* parent): parent(parent) { m_pimpl = std::make_unique().release(); } @@ -50,142 +54,210 @@ bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { auto pimpl = (PImpl*)m_pimpl; - // Init Setup - // auto aBufferIo = (uint8_t*)av_malloc(4096 + AV_INPUT_BUFFER_PADDING_SIZE); + if (param->data == nullptr) { + // Reset + parent->state.bits.Empty = true; - // AVIOContext* avioctx = avio_alloc_context(aBufferIo, 4096, 0, &userData, readFunc_linearBuffer, nullptr, seekFunc_linearBuffer); + delete pimpl; + m_pimpl = std::make_unique().release(); + return true; + } - // cleanup.emplace_back([&] { av_free(avioctx); }); - // cleanup.emplace_back([&] { av_free(aBufferIo); }); + pimpl->data = (uint8_t const*)param->data; + pimpl->block = param->aBlock[0]; + pimpl->curOffset = 0; - // // Open the input - // pimpl->fmtctx = avformat_alloc_context(); - // cleanup.emplace_back([&] { avformat_free_context(pimpl->fmtctx); }); + // Check if riff or uncompressed + auto riffHeader = (RiffWaveHeader const*)param->data; + if (memcmp(riffHeader->chunkID, "RIFF", 4) != 0 || memcmp(riffHeader->riffType, "WAVE", 4) != 0) { + m_isCompressed = false; + return true; + } - // pimpl->fmtctx->pb = avioctx; - // pimpl->fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; + // parse riff + m_isCompressed = true; - // int ret = avformat_open_input(&pimpl->fmtctx, "nullptr", nullptr, nullptr); - // if (ret != 0) { - // LOG_ERR(L"Reader: ffmpeg failed to read passed data: %d", ret); - // return false; - // } - // cleanup.emplace_back([&] { avformat_close_input(&pimpl->fmtctx); }); + auto cleanup = &pimpl->cleanup; + auto userData = &pimpl->userData; - // pimpl->stream_idx = av_find_best_stream(pimpl->fmtctx, AVMEDIA_TYPE_AUDIO, -1, -1, &pimpl->codec, 0); + userData->ptr = param->data; + userData->size = param->aBlock[0].offset + param->aBlock[0].size; + userData->curOffset = 0; - // if (pimpl->stream_idx < 0) { - // LOG_ERR(L"Reader: no audio stream"); - // return false; - // } + pimpl->newPacket = true; - // pimpl->astream = pimpl->fmtctx->streams[pimpl->stream_idx]; + // Init Setup + auto aBufferIo = (uint8_t*)av_malloc(4096 + AV_INPUT_BUFFER_PADDING_SIZE); - // pimpl->codecContext = avcodec_alloc_context3(pimpl->codec); - // if (auto err = avcodec_parameters_to_context(pimpl->codecContext, pimpl->astream->codecpar); err != 0) { - // LOG_ERR(L"Reader: avcodec_parameters_to_context err:%d", err); - // return false; - // } - // cleanup.emplace_back([&] { avcodec_free_context(&pimpl->codecContext); }); + AVIOContext* avioctx = avio_alloc_context(aBufferIo, 4096, 0, userData, readFunc_linearBuffer, nullptr, seekFunc_linearBuffer); - // // Setup multithreading - // if (pimpl->codec->capabilities | AV_CODEC_CAP_FRAME_THREADS) - // pimpl->codecContext->thread_type = FF_THREAD_FRAME; - // else if (pimpl->codec->capabilities | AV_CODEC_CAP_SLICE_THREADS) - // pimpl->codecContext->thread_type = FF_THREAD_SLICE; - // else - // pimpl->codecContext->thread_count = 1; // don't use multithreading - // // - + cleanup->emplace_back([&] { av_free(avioctx); }); + cleanup->emplace_back([&] { av_free(aBufferIo); }); - // if (auto err = avcodec_open2(pimpl->codecContext, pimpl->codec, NULL); err < 0) { - // LOG_ERR(L"Reader: avcodec_open2 err:%d", err); - // return false; - // } + // Open the input + pimpl->fmtctx = avformat_alloc_context(); - // if (swr_alloc_set_opts2(&pimpl->swrCtx, &pimpl->codecContext->ch_layout, AVSampleFormat::AV_SAMPLE_FMT_S16, pimpl->codecContext->sample_rate, - // &pimpl->codecContext->ch_layout, pimpl->codecContext->sample_fmt, pimpl->codecContext->sample_rate, 0, NULL)) { - // LOG_ERR(L"Reader:Couldn't alloc swr"); - // return false; - // } + pimpl->fmtctx->pb = avioctx; + pimpl->fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; - // swr_init(pimpl->swrCtx); - // cleanup.emplace_back([&] { swr_free(&pimpl->swrCtx); }); + int ret = avformat_open_input(&pimpl->fmtctx, "nullptr", nullptr, nullptr); + if (ret != 0) { + LOG_ERR(L"Reader: ffmpeg failed to read passed data: %d", ret); + return false; + } + cleanup->emplace_back([&] { avformat_close_input(&pimpl->fmtctx); }); - // pimpl->frame = av_frame_alloc(); - // cleanup.emplace_back([&] { av_frame_free(&pimpl->frame); }); + if (int res = avformat_find_stream_info(pimpl->fmtctx, NULL) < 0; res < 0) { + LOG_ERR(L"avformat_find_stream_info result:%d", res); + return false; + } - // pimpl->packet = av_packet_alloc(); - // cleanup.emplace_back([&] { av_packet_free(&pimpl->packet); }); + pimpl->astream = pimpl->fmtctx->streams[pimpl->stream_idx]; - m_isInit = true; + pimpl->codec = avcodec_find_decoder(pimpl->astream->codecpar->codec_id); + pimpl->codecContext = avcodec_alloc_context3(pimpl->codec); + if (auto err = avcodec_parameters_to_context(pimpl->codecContext, pimpl->astream->codecpar); err != 0) { + LOG_ERR(L"Reader: avcodec_parameters_to_context err:%d", err); + return false; + } + cleanup->emplace_back([&] { avcodec_free_context(&pimpl->codecContext); }); + + // Setup multithreading + if (pimpl->codec->capabilities | AV_CODEC_CAP_FRAME_THREADS) + pimpl->codecContext->thread_type = FF_THREAD_FRAME; + else if (pimpl->codec->capabilities | AV_CODEC_CAP_SLICE_THREADS) + pimpl->codecContext->thread_type = FF_THREAD_SLICE; + else + pimpl->codecContext->thread_count = 1; // don't use multithreading + // - + + if (auto err = avcodec_open2(pimpl->codecContext, pimpl->codec, NULL); err < 0) { + LOG_ERR(L"Reader: avcodec_open2 err:%d", err); + return false; + } + + AVChannelLayout dstChLayout = AV_CHANNEL_LAYOUT_7POINT1; + if (swr_alloc_set_opts2(&pimpl->swrCtx, &dstChLayout, AVSampleFormat::AV_SAMPLE_FMT_FLT, parent->info.sampleRate, &pimpl->codecContext->ch_layout, + pimpl->codecContext->sample_fmt, pimpl->codecContext->sample_rate, 0, NULL)) { + LOG_ERR(L"Reader:Couldn't alloc swr"); + return false; + } + + swr_init(pimpl->swrCtx); + cleanup->emplace_back([&] { swr_free(&pimpl->swrCtx); }); + + pimpl->frame = av_frame_alloc(); + cleanup->emplace_back([&] { av_frame_free(&pimpl->frame); }); + + pimpl->packet = av_packet_alloc(); + cleanup->emplace_back([&] { av_packet_free(&pimpl->packet); }); + + m_isInit = true; + parent->state.bits.Empty = false; return true; } -bool Reader::getAudio(SceNgs2Handle_voice* handle, void* buffer, size_t bufferSize) { - if (m_isInit == false || !handle->state.bits.Playing || (handle->state.bits.Playing && handle->state.bits.Paused)) { - std::memset(buffer, 0, bufferSize); - return true; +bool Reader::getAudioUncompressed(void* buffer, size_t bufferSize) { + auto pimpl = (PImpl*)m_pimpl; + + // Check repeat + if (pimpl->block.size <= pimpl->curOffset) { + if (pimpl->block.numRepeat > 0) { + pimpl->curOffset = 0; + --pimpl->block.numRepeat; + } else { + parent->state.bits.Empty = true; + return false; + } } + // - + + uint32_t const readSize = std::min(bufferSize, (size_t)pimpl->block.size - pimpl->curOffset); + + std::memcpy(buffer, pimpl->data + pimpl->curOffset, readSize); + pimpl->curOffset += readSize; + + return true; +} + +bool Reader::getAudioCompressed(void* buffer, size_t bufferSize) { LOG_USE_MODULE(libSceNgs2); auto pimpl = (PImpl*)m_pimpl; - std::memset(buffer, 0, bufferSize); - - // size_t offset = 0; - - // int const outNumSamples = swr_get_out_samples(pimpl->swrCtx, pimpl->frame->nb_samples); - // auto const bufferSize_ = pimpl->frame->ch_layout.nb_channels * outNumSamples * av_get_bytes_per_sample((AVSampleFormat)pimpl->frame->format); - - // while (offset < bufferSize) { - // // Get a new packet - // if (pimpl->packet == nullptr) { - // int state = av_read_frame(pimpl->fmtctx, pimpl->packet); - // if (state < 0) { - // if (state != AVERROR_EOF) { - // LOG_ERR(L"av_read_frame error %d", state); - // } else { - // handle->state.bits.Empty = true; - // handle->state.bits.Playing = false; - // } - // std::memset(buffer, 0, bufferSize); - // return false; - // } - // } - // // - - - // // Process packet - // if (int ret = avcodec_send_packet(pimpl->codecContext, pimpl->packet); ret < 0) { - // if (ret == AVERROR(EAGAIN)) { - // av_packet_unref(pimpl->packet); - // pimpl->packet = nullptr; - // continue; // Get new frame - // } else if (ret == AVERROR_EOF) { - // handle->state.bits.Empty = true; - // } else { - // handle->state.bits.Error = true; - // } - // handle->state.bits.Playing = false; - // std::memset(buffer, 0, bufferSize); - // return false; - // } - - // av_packet_unref(pimpl->packet); - // //- packet - - // // Now the frames - // auto const retRecv = avcodec_receive_frame(pimpl->codecContext, pimpl->frame); - - // uint8_t* audioBuffers[1] = {(uint8_t*)buffer + offset}; - // if (swr_convert(pimpl->swrCtx, audioBuffers, outNumSamples, (uint8_t const**)pimpl->frame->extended_data, pimpl->frame->nb_samples) < 0) { - // LOG_WARN(L"swr_convert"); - // } - - // av_frame_unref(pimpl->frame); - // // - - - // offset += bufferSize_; - // } + size_t offset = 0; + + while (offset < bufferSize) { + // Get a new packet + if (pimpl->newPacket) { + pimpl->packet->dts = AV_NOPTS_VALUE; + pimpl->packet->pts = AV_NOPTS_VALUE; + + int state = av_read_frame(pimpl->fmtctx, pimpl->packet); + + pimpl->newPacket = false; + if (state < 0) { + if (state != AVERROR_EOF) { + LOG_ERR(L"av_read_frame error %d", state); + } else { + parent->state.bits.Empty = true; + parent->state.bits.Playing = false; + } + return false; + } + } + // - + + // Process packet + if (int ret = avcodec_send_packet(pimpl->codecContext, pimpl->packet); ret < 0) { + if (ret == AVERROR(EAGAIN)) { + av_packet_unref(pimpl->packet); + pimpl->newPacket = true; + continue; // Get new frame + } else if (ret == AVERROR_EOF) { + parent->state.bits.Empty = true; + } else { + parent->state.bits.Error = true; + } + parent->state.bits.Playing = false; + + return false; + } + + av_packet_unref(pimpl->packet); + //- packet + + // Now the frames + auto const retRecv = avcodec_receive_frame(pimpl->codecContext, pimpl->frame); + + int outNumSamples = swr_get_out_samples(pimpl->swrCtx, pimpl->frame->nb_samples); + + // todo get sample size, nb_channels is zero (fix) + uint8_t* audioBuffers[1] = {&((uint8_t*)buffer)[offset]}; + if (outNumSamples = swr_convert(pimpl->swrCtx, audioBuffers, outNumSamples, (uint8_t const**)pimpl->frame->extended_data, pimpl->frame->nb_samples); + outNumSamples < 0) { + LOG_WARN(L"swr_convert"); + } + + av_frame_unref(pimpl->frame); + // - + + auto const bufferSize_ = pimpl->codecContext->ch_layout.nb_channels * outNumSamples * av_get_bytes_per_sample(pimpl->codecContext->sample_fmt); + offset += bufferSize_; + } + return true; +} + +bool Reader::getAudio(void* buffer, size_t bufferSize) { + if (m_isInit == false || !parent->state.bits.Playing || (parent->state.bits.Playing && parent->state.bits.Paused)) { + return true; + } + + if (m_isCompressed) { + return getAudioCompressed(buffer, bufferSize); + } else { + return getAudioUncompressed(buffer, bufferSize); + } return true; } \ No newline at end of file diff --git a/modules/libSceNgs2/reader.h b/modules/libSceNgs2/reader.h index 98416361..b4de1989 100644 --- a/modules/libSceNgs2/reader.h +++ b/modules/libSceNgs2/reader.h @@ -5,13 +5,19 @@ struct SceNgs2SamplerVoiceWaveformBlocksParam; class Reader { void* m_pimpl; - bool m_isInit = false; + bool m_isInit = false; + bool m_isCompressed = false; + + SceNgs2Handle_voice* parent; + + bool getAudioUncompressed(void* buffer, size_t bufferSize); + bool getAudioCompressed(void* buffer, size_t bufferSize); public: - Reader(); + Reader(SceNgs2Handle_voice* handle); ~Reader(); bool init(SceNgs2SamplerVoiceWaveformBlocksParam const* param); - bool getAudio(SceNgs2Handle_voice* handle, void* buffer, size_t bufferSize); + bool getAudio(void* buffer, size_t bufferSize); }; \ No newline at end of file diff --git a/modules/libSceNgs2/riffTypes.h b/modules/libSceNgs2/riffTypes.h new file mode 100644 index 00000000..7d4e5198 --- /dev/null +++ b/modules/libSceNgs2/riffTypes.h @@ -0,0 +1,24 @@ +#pragma once +#include + +struct RiffHeader { + unsigned char chunkID[4]; // RIFF + uint32_t chunkSize; +} __attribute__((packed)); + +struct RiffWaveHeader { + unsigned char chunkID[4]; // RIFF + uint32_t chunkSize; + unsigned char riffType[4]; // WAVE +} __attribute__((packed)); + +struct RiffFormatHeader { + unsigned char chunkID[4]; // RIFF + uint32_t chunkSize; + uint16_t audioFormat; + uint16_t numChannels; + uint32_t sampleRate; // Sampling Frequency in Hz + uint32_t avgByteRate; // ~bytes per second + uint16_t frameSize; // BlockAlign + uint16_t bitsPerSample; +} __attribute__((packed)); \ No newline at end of file diff --git a/modules/libSceNgs2/types.h b/modules/libSceNgs2/types.h index 712cc018..c81d2b7f 100644 --- a/modules/libSceNgs2/types.h +++ b/modules/libSceNgs2/types.h @@ -3,6 +3,7 @@ #include "codes.h" #include "utility/utility.h" +#include #include union SceNgs2VoiceStateFlags { @@ -258,8 +259,9 @@ struct SceNgs2Handle_rack: public SceNgs2Handle { SceNgs2Handle_system* parent; - SceNgs2RackOption options; - SceNgs2Handle_voice* voices; + SceNgs2RackOption options; + + std::map voices; // address of SceNgs2Handle_voice must be valid ! SceNgs2Handle_rack(SceNgs2Handle_system* parent, SceNgs2RackOption const* options_, uint32_t rackId) : SceNgs2Handle(SceNgs2HandleType::Rack), rackId(rackId), parent(parent) { From 10fa8fbcdebb079d63e8bf6b78268a69eec69aab Mon Sep 17 00:00:00 2001 From: Martin Baliet Date: Wed, 8 May 2024 18:04:21 +0200 Subject: [PATCH 07/19] audioOut| use information form opened device --- modules/libSceAudioOut/entry.cpp | 51 +++++++++++++------------------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/modules/libSceAudioOut/entry.cpp b/modules/libSceAudioOut/entry.cpp index ce159c17..a52dde37 100644 --- a/modules/libSceAudioOut/entry.cpp +++ b/modules/libSceAudioOut/entry.cpp @@ -19,8 +19,8 @@ struct PortOut { int userId = 0; SceAudioOutPortType type = SceAudioOutPortType::MAIN; uint8_t sampleSize = 0; - uint32_t samplesNum = 0; uint32_t sampleRate = 0; + uint32_t samplesNum = 0; uint32_t queued = 0; SceAudioOutParamFormat format = SceAudioOutParamFormat::FLOAT_MONO; uint64_t lastOutputTime = 0; @@ -31,6 +31,8 @@ struct PortOut { float volumeModifier = 0.5f; std::vector mixedAudio; std::string deviceName; + + SDL_AudioSpec audioSpec; }; class PortsOut { @@ -70,16 +72,7 @@ class PortsOut { */ if (port.deviceName.compare(0, std::string::npos, devName, 0, port.deviceName.length()) != 0) continue; - SDL_AudioSpec fmt { - .freq = static_cast(port.sampleRate), - .format = port.sdlFormat, - .channels = static_cast(port.channelsNum), - .samples = static_cast(port.samplesNum), - .callback = nullptr, - .userdata = nullptr, - }; - - if ((port.device = SDL_OpenAudioDevice(devName, 0, &fmt, NULL, 0)) == 0) { + if ((port.device = SDL_OpenAudioDevice(devName, 0, &port.audioSpec, NULL, 0)) == 0) { LOG_ERR(L"Failed to reopen %S audio device: %S", devName, SDL_GetError()); return; } @@ -200,12 +193,11 @@ int writeOut(PortOut* port, const void* ptr, bool sync = true) { return port->samplesNum; } - const uint32_t bytesize = bytesize_1ch * port->channelsNum; - const int maxVolume = SDL_MIX_MAXVOLUME * port->volumeModifier; - auto& mixed = port->mixedAudio; + const int maxVolume = SDL_MIX_MAXVOLUME * port->volumeModifier; + auto& mixed = port->mixedAudio; std::fill(mixed.begin(), mixed.end(), 0); - for (int i = 0; i < port->channelsNum; i++) { + for (int i = 0; i < port->audioSpec.channels; i++) { auto ch_offset = i * bytesize_1ch; SDL_MixAudioFormat(mixed.data() + ch_offset, ((const uint8_t*)ptr) + ch_offset, port->sdlFormat, bytesize_1ch, maxVolume * ((float)port->volume[i] / AudioOut::VOLUME_0DB)); @@ -213,7 +205,7 @@ int writeOut(PortOut* port, const void* ptr, bool sync = true) { if (SDL_GetAudioDeviceStatus(port->device) != SDL_AUDIO_PLAYING) SDL_PauseAudioDevice(port->device, 0); - int ret = SDL_QueueAudio(port->device, mixed.data(), bytesize); + int ret = SDL_QueueAudio(port->device, mixed.data(), port->audioSpec.size); if (ret == 0) port->queued = SDL_GetQueuedAudioSize(port->device); if (sync) syncPort(port); @@ -321,6 +313,15 @@ EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type port->volumeModifier = 0.5f; } + SDL_AudioSpec audioSpec = { + .freq = static_cast(sampleRate), + .format = port->sdlFormat, + .channels = static_cast(port->channelsNum), + .samples = static_cast(port->samplesNum), + .callback = nullptr, + .userdata = nullptr, + }; + if (type == SceAudioOutPortType::PADSPK) { auto& devn = (*jData)["padspeakers"][userId - 1]; @@ -343,9 +344,8 @@ EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type port->volume[i] = AudioOut::MIXLEVEL_PADSPK_0DB; } } else { - SDL_AudioSpec fmt_curr; if ((*jData)["device"] == "[default]") { - if (SDL_GetDefaultAudioInfo((char**)&dname, &fmt_curr, 0) != 0) { + if (SDL_GetDefaultAudioInfo((char**)&dname, &port->audioSpec, 0) != 0) { LOG_ERR(L"Failed to get the default audio device, port #%d is nulled! (%S)", handle, SDL_GetError()); port->device = 0; return handle; @@ -361,7 +361,7 @@ EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type } catch (const json::exception& e) { LOG_ERR(L"Invalid audio device name: %S, falling back to default", e.what()); dname = NULL; - if (SDL_GetDefaultAudioInfo((char**)&dname, &fmt_curr, 0) != 0) { + if (SDL_GetDefaultAudioInfo((char**)&dname, &port->audioSpec, 0) != 0) { LOG_ERR(L"Falling back to default device failed, port #%d is nulled! (%S)", handle, SDL_GetError()); port->device = 0; return handle; @@ -374,16 +374,7 @@ EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type } } - SDL_AudioSpec fmt { - .freq = static_cast(sampleRate), - .format = port->sdlFormat, - .channels = static_cast(port->channelsNum), - .samples = static_cast(port->samplesNum), - .callback = nullptr, - .userdata = nullptr, - }; - - if ((port->device = SDL_OpenAudioDevice(dname, 0, &fmt, NULL, 0)) == 0) { + if ((port->device = SDL_OpenAudioDevice(dname, 0, &audioSpec, &port->audioSpec, 0)) == 0) { LOG_ERR(L"Failed to open %S audio device: %S", getDevName(type), SDL_GetError()); // Since audio connect/disconnect event is implemented now, we can fall through there. // The audio device will be opened automatically when available. @@ -391,7 +382,7 @@ EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type LOG_INFO(L"%S audio device %S opened for user #%d", getDevName(type), dname, userId); } - port->mixedAudio.resize(port->sampleSize * port->samplesNum * port->channelsNum); + port->mixedAudio.resize(port->audioSpec.size); port->deviceName.assign(dname); return handle; } From 026a889280f9db9c2b5b605e90ec6d2bbea228fc Mon Sep 17 00:00:00 2001 From: SysRay Date: Thu, 9 May 2024 14:10:51 +0200 Subject: [PATCH 08/19] ngs2| dump --- modules/libSceNgs2/entry.cpp | 4 +- modules/libSceNgs2/readFuncs.cpp | 42 +++++++++++ modules/libSceNgs2/readFuncs.h | 8 ++- modules/libSceNgs2/reader.cpp | 119 +++++++++++++++++++++---------- modules/libSceNgs2/reader.h | 13 ++-- modules/libSceNgs2/types.h | 8 +-- 6 files changed, 144 insertions(+), 50 deletions(-) diff --git a/modules/libSceNgs2/entry.cpp b/modules/libSceNgs2/entry.cpp index 9b7cc5e4..2ce34110 100644 --- a/modules/libSceNgs2/entry.cpp +++ b/modules/libSceNgs2/entry.cpp @@ -555,6 +555,8 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBu if (rbi->waveType >= SceNgs2WaveFormType::MAX_TYPES) return Err::Ngs2::INVALID_WAVEFORM_TYPE; if (rbi->channelsCount > SceNgs2ChannelsCount::CH_7_1) return Err::Ngs2::INVALID_NUM_CHANNELS; + // uint32_t const numSamples = rbi->bufferSize / ((uint32_t)rbi->channelsCount * getSampleBytes(rbi->waveType)); + if (system->sampler == nullptr) { // for (int32_t i = 0; i < count; i++) { @@ -569,7 +571,7 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBu std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); for (auto& voice: system->sampler->voices) { if (voice.second.reader != nullptr) { - voice.second.reader->getAudio(rbi[i].bufferPtr, rbi[i].bufferSize); + voice.second.reader->getAudio(&rbi[i]); } } } diff --git a/modules/libSceNgs2/readFuncs.cpp b/modules/libSceNgs2/readFuncs.cpp index f7a52843..2a998ae8 100644 --- a/modules/libSceNgs2/readFuncs.cpp +++ b/modules/libSceNgs2/readFuncs.cpp @@ -192,4 +192,46 @@ int32_t parseRiffWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* user wf->numBlocks = 1; return Ok; +} + +std::optional convChannelLayout(SceNgs2ChannelsCount count) { + LOG_USE_MODULE(libSceNgs2); + switch (count) { + case SceNgs2ChannelsCount::CH_1_0: { + return {AV_CHANNEL_LAYOUT_MONO}; + } break; + case SceNgs2ChannelsCount::CH_2_0: { + return {AV_CHANNEL_LAYOUT_STEREO}; + } break; + case SceNgs2ChannelsCount::CH_5_1: { + return {AV_CHANNEL_LAYOUT_5POINT1}; + } break; + case SceNgs2ChannelsCount::CH_7_1: { + return {AV_CHANNEL_LAYOUT_CUBE}; + } break; + default: { + LOG_ERR(L"channel layout not set"); + } break; + } + return std::nullopt; +} + +uint32_t getSampleBytes(SceNgs2WaveFormType type) { + switch (type) { + case SceNgs2WaveFormType::PCM_U8: return 1; + case SceNgs2WaveFormType::PCM_I16LITTLE: return 2; + case SceNgs2WaveFormType::PCM_I16BIG: return 2; + case SceNgs2WaveFormType::PCM_I24LITTLE: return 3; + case SceNgs2WaveFormType::PCM_I24BIG: return 3; + case SceNgs2WaveFormType::PCM_I32LITTLE: return 4; + case SceNgs2WaveFormType::PCM_I32BIG: return 4; + case SceNgs2WaveFormType::PCM_F32LITTLE: return 4; + case SceNgs2WaveFormType::PCM_F32BIG: return 4; + case SceNgs2WaveFormType::PCM_F64LITTLE: return 8; + case SceNgs2WaveFormType::PCM_F64BIG: return 8; + case SceNgs2WaveFormType::VAG: return 4; + case SceNgs2WaveFormType::ATRAC9: return 4; + default: break; + } + return 2; } \ No newline at end of file diff --git a/modules/libSceNgs2/readFuncs.h b/modules/libSceNgs2/readFuncs.h index 1aeed42c..5049fd92 100644 --- a/modules/libSceNgs2/readFuncs.h +++ b/modules/libSceNgs2/readFuncs.h @@ -1,6 +1,8 @@ #pragma once #include "types.h" +#include + using funcReadBuf_t = int (*)(void*, uint8_t*, int); using funcSeekBuf_t = int64_t (*)(void*, int64_t, int); @@ -23,4 +25,8 @@ int64_t seekFunc_file(void* userData_, int64_t offset, int whence); int readFunc_user(void* userData_, uint8_t* buf, int size); int64_t seekFunc_user(void* userData_, int64_t offset, int whence); -int32_t parseRiffWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData, SceNgs2WaveformFormat* wf); \ No newline at end of file +int32_t parseRiffWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData, SceNgs2WaveformFormat* wf); + +std::optional convChannelLayout(SceNgs2ChannelsCount); + +uint32_t getSampleBytes(SceNgs2WaveFormType); \ No newline at end of file diff --git a/modules/libSceNgs2/reader.cpp b/modules/libSceNgs2/reader.cpp index 5e90bb2f..0b3edca9 100644 --- a/modules/libSceNgs2/reader.cpp +++ b/modules/libSceNgs2/reader.cpp @@ -17,6 +17,27 @@ extern "C" { LOG_DEFINE_MODULE(libSceNgs2); namespace { + +AVSampleFormat convFormat(SceNgs2WaveFormType type) { + switch (type) { + case SceNgs2WaveFormType::PCM_U8: return AVSampleFormat::AV_SAMPLE_FMT_U8; + case SceNgs2WaveFormType::PCM_I16LITTLE: return AVSampleFormat::AV_SAMPLE_FMT_S16; + case SceNgs2WaveFormType::PCM_I16BIG: return AVSampleFormat::AV_SAMPLE_FMT_S16; + case SceNgs2WaveFormType::PCM_I24LITTLE: return AVSampleFormat::AV_SAMPLE_FMT_NONE; + case SceNgs2WaveFormType::PCM_I24BIG: return AVSampleFormat::AV_SAMPLE_FMT_NONE; + case SceNgs2WaveFormType::PCM_I32LITTLE: return AVSampleFormat::AV_SAMPLE_FMT_S32; + case SceNgs2WaveFormType::PCM_I32BIG: return AVSampleFormat::AV_SAMPLE_FMT_S32; + case SceNgs2WaveFormType::PCM_F32LITTLE: return AVSampleFormat::AV_SAMPLE_FMT_FLT; + case SceNgs2WaveFormType::PCM_F32BIG: return AVSampleFormat::AV_SAMPLE_FMT_FLT; + case SceNgs2WaveFormType::PCM_F64LITTLE: return AVSampleFormat::AV_SAMPLE_FMT_DBL; + case SceNgs2WaveFormType::PCM_F64BIG: return AVSampleFormat::AV_SAMPLE_FMT_DBL; + case SceNgs2WaveFormType::VAG: return AVSampleFormat::AV_SAMPLE_FMT_FLT; // todo + case SceNgs2WaveFormType::ATRAC9: return AVSampleFormat::AV_SAMPLE_FMT_FLT; // todo + default: break; + } + return AVSampleFormat::AV_SAMPLE_FMT_NONE; +} + struct PImpl { std::list> cleanup; @@ -41,7 +62,7 @@ struct PImpl { }; } // namespace -Reader::Reader(SceNgs2Handle_voice* parent): parent(parent) { +Reader::Reader(SceNgs2Handle_voice* voice): voice(voice) { m_pimpl = std::make_unique().release(); } @@ -51,17 +72,19 @@ Reader::~Reader() { bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { LOG_USE_MODULE(libSceNgs2); + if (m_isInit) return true; // todo auto pimpl = (PImpl*)m_pimpl; if (param->data == nullptr) { // Reset - parent->state.bits.Empty = true; + voice->state.bits.Empty = true; delete pimpl; m_pimpl = std::make_unique().release(); return true; } + m_isInit = false; pimpl->data = (uint8_t const*)param->data; pimpl->block = param->aBlock[0]; @@ -100,11 +123,12 @@ bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { pimpl->fmtctx->pb = avioctx; pimpl->fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; - int ret = avformat_open_input(&pimpl->fmtctx, "nullptr", nullptr, nullptr); + int ret = avformat_open_input(&pimpl->fmtctx, nullptr, nullptr, nullptr); if (ret != 0) { LOG_ERR(L"Reader: ffmpeg failed to read passed data: %d", ret); return false; } + cleanup->emplace_back([&] { avformat_close_input(&pimpl->fmtctx); }); if (int res = avformat_find_stream_info(pimpl->fmtctx, NULL) < 0; res < 0) { @@ -112,9 +136,8 @@ bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { return false; } - pimpl->astream = pimpl->fmtctx->streams[pimpl->stream_idx]; - - pimpl->codec = avcodec_find_decoder(pimpl->astream->codecpar->codec_id); + pimpl->stream_idx = av_find_best_stream(pimpl->fmtctx, AVMEDIA_TYPE_AUDIO, -1, -1, &pimpl->codec, 0); + pimpl->astream = pimpl->fmtctx->streams[pimpl->stream_idx]; pimpl->codecContext = avcodec_alloc_context3(pimpl->codec); if (auto err = avcodec_parameters_to_context(pimpl->codecContext, pimpl->astream->codecpar); err != 0) { @@ -137,28 +160,18 @@ bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { return false; } - AVChannelLayout dstChLayout = AV_CHANNEL_LAYOUT_7POINT1; - if (swr_alloc_set_opts2(&pimpl->swrCtx, &dstChLayout, AVSampleFormat::AV_SAMPLE_FMT_FLT, parent->info.sampleRate, &pimpl->codecContext->ch_layout, - pimpl->codecContext->sample_fmt, pimpl->codecContext->sample_rate, 0, NULL)) { - LOG_ERR(L"Reader:Couldn't alloc swr"); - return false; - } - - swr_init(pimpl->swrCtx); - cleanup->emplace_back([&] { swr_free(&pimpl->swrCtx); }); - pimpl->frame = av_frame_alloc(); cleanup->emplace_back([&] { av_frame_free(&pimpl->frame); }); pimpl->packet = av_packet_alloc(); cleanup->emplace_back([&] { av_packet_free(&pimpl->packet); }); - m_isInit = true; - parent->state.bits.Empty = false; + m_isInit = true; + voice->state.bits.Empty = false; return true; } -bool Reader::getAudioUncompressed(void* buffer, size_t bufferSize) { +bool Reader::getAudioUncompressed(SceNgs2RenderBufferInfo* rbi) { auto pimpl = (PImpl*)m_pimpl; // Check repeat @@ -167,45 +180,68 @@ bool Reader::getAudioUncompressed(void* buffer, size_t bufferSize) { pimpl->curOffset = 0; --pimpl->block.numRepeat; } else { - parent->state.bits.Empty = true; + voice->state.bits.Empty = true; return false; } } // - - uint32_t const readSize = std::min(bufferSize, (size_t)pimpl->block.size - pimpl->curOffset); + uint32_t const readSize = std::min(rbi->bufferSize, (size_t)pimpl->block.size - pimpl->curOffset); - std::memcpy(buffer, pimpl->data + pimpl->curOffset, readSize); + std::memcpy(rbi->bufferPtr, pimpl->data + pimpl->curOffset, readSize); pimpl->curOffset += readSize; return true; } -bool Reader::getAudioCompressed(void* buffer, size_t bufferSize) { +bool Reader::getAudioCompressed(SceNgs2RenderBufferInfo* rbi) { LOG_USE_MODULE(libSceNgs2); auto pimpl = (PImpl*)m_pimpl; + if (pimpl->swrCtx == nullptr) { + auto optDstChLayout = convChannelLayout(rbi->channelsCount); + if (!optDstChLayout) { + return false; + } + auto format = convFormat(rbi->waveType); + if (format == AVSampleFormat::AV_SAMPLE_FMT_NONE) return false; + + if (swr_alloc_set_opts2(&pimpl->swrCtx, &(*optDstChLayout), format, voice->info.sampleRate, &pimpl->codecContext->ch_layout, + pimpl->codecContext->sample_fmt, pimpl->codecContext->sample_rate, 0, NULL)) { + LOG_ERR(L"Reader:Couldn't alloc swr"); + return false; + } + + swr_init(pimpl->swrCtx); + pimpl->cleanup.emplace_back([&] { swr_free(&pimpl->swrCtx); }); + } + size_t offset = 0; - while (offset < bufferSize) { + while (offset < rbi->bufferSize) { // Get a new packet if (pimpl->newPacket) { pimpl->packet->dts = AV_NOPTS_VALUE; pimpl->packet->pts = AV_NOPTS_VALUE; int state = av_read_frame(pimpl->fmtctx, pimpl->packet); - - pimpl->newPacket = false; if (state < 0) { if (state != AVERROR_EOF) { LOG_ERR(L"av_read_frame error %d", state); } else { - parent->state.bits.Empty = true; - parent->state.bits.Playing = false; + voice->state.bits.Empty = true; + voice->state.bits.Playing = false; } return false; } + + // Skip if not a audio packet + if (pimpl->packet->stream_index != pimpl->stream_idx) { + continue; + } + + pimpl->newPacket = false; } // - @@ -216,11 +252,11 @@ bool Reader::getAudioCompressed(void* buffer, size_t bufferSize) { pimpl->newPacket = true; continue; // Get new frame } else if (ret == AVERROR_EOF) { - parent->state.bits.Empty = true; + voice->state.bits.Empty = true; } else { - parent->state.bits.Error = true; + voice->state.bits.Error = true; } - parent->state.bits.Playing = false; + voice->state.bits.Playing = false; return false; } @@ -234,8 +270,9 @@ bool Reader::getAudioCompressed(void* buffer, size_t bufferSize) { int outNumSamples = swr_get_out_samples(pimpl->swrCtx, pimpl->frame->nb_samples); // todo get sample size, nb_channels is zero (fix) - uint8_t* audioBuffers[1] = {&((uint8_t*)buffer)[offset]}; - if (outNumSamples = swr_convert(pimpl->swrCtx, audioBuffers, outNumSamples, (uint8_t const**)pimpl->frame->extended_data, pimpl->frame->nb_samples); + uint8_t* audioBuffers[1] = {&((uint8_t*)rbi->bufferPtr)[offset]}; + + if (outNumSamples = swr_convert(pimpl->swrCtx, audioBuffers, outNumSamples, (uint8_t const**)pimpl->frame->data, pimpl->frame->nb_samples); outNumSamples < 0) { LOG_WARN(L"swr_convert"); } @@ -243,21 +280,27 @@ bool Reader::getAudioCompressed(void* buffer, size_t bufferSize) { av_frame_unref(pimpl->frame); // - - auto const bufferSize_ = pimpl->codecContext->ch_layout.nb_channels * outNumSamples * av_get_bytes_per_sample(pimpl->codecContext->sample_fmt); + auto const bufferSize_ = (uint32_t)rbi->channelsCount * outNumSamples * av_get_bytes_per_sample(convFormat(rbi->waveType)); + + // float* samples = (float*)(&((uint8_t*)rbi->bufferPtr)[offset]); + // for (int i = 0; i < outNumSamples * (int)rbi->channelsCount; i++) { + // samples[i] *= 100000.0; + // } + offset += bufferSize_; } return true; } -bool Reader::getAudio(void* buffer, size_t bufferSize) { - if (m_isInit == false || !parent->state.bits.Playing || (parent->state.bits.Playing && parent->state.bits.Paused)) { +bool Reader::getAudio(SceNgs2RenderBufferInfo* rbi) { + if (m_isInit == false || !voice->state.bits.Playing || (voice->state.bits.Playing && voice->state.bits.Paused)) { return true; } if (m_isCompressed) { - return getAudioCompressed(buffer, bufferSize); + return getAudioCompressed(rbi); } else { - return getAudioUncompressed(buffer, bufferSize); + return getAudioUncompressed(rbi); } return true; } \ No newline at end of file diff --git a/modules/libSceNgs2/reader.h b/modules/libSceNgs2/reader.h index b4de1989..abccd367 100644 --- a/modules/libSceNgs2/reader.h +++ b/modules/libSceNgs2/reader.h @@ -2,22 +2,23 @@ struct SceNgs2Handle_voice; struct SceNgs2SamplerVoiceWaveformBlocksParam; +struct SceNgs2RenderBufferInfo; class Reader { void* m_pimpl; bool m_isInit = false; bool m_isCompressed = false; - SceNgs2Handle_voice* parent; + SceNgs2Handle_voice* voice; - bool getAudioUncompressed(void* buffer, size_t bufferSize); - bool getAudioCompressed(void* buffer, size_t bufferSize); + bool getAudioUncompressed(SceNgs2RenderBufferInfo*); + bool getAudioCompressed(SceNgs2RenderBufferInfo*); public: - Reader(SceNgs2Handle_voice* handle); + Reader(SceNgs2Handle_voice* voice); ~Reader(); bool init(SceNgs2SamplerVoiceWaveformBlocksParam const* param); - bool getAudio(void* buffer, size_t bufferSize); -}; \ No newline at end of file + bool getAudio(SceNgs2RenderBufferInfo*); +}; diff --git a/modules/libSceNgs2/types.h b/modules/libSceNgs2/types.h index c81d2b7f..5e443a72 100644 --- a/modules/libSceNgs2/types.h +++ b/modules/libSceNgs2/types.h @@ -117,9 +117,9 @@ enum class SceNgs2SubmixerParam : uint16_t { #pragma pack(push, 1) struct SceNgs2WaveformInfo { - SceNgs2WaveFormType type; - SceNgs2ChannelsCount channelsCount; - uint32_t sampleRate; + SceNgs2WaveFormType type = SceNgs2WaveFormType::NONE; + SceNgs2ChannelsCount channelsCount = SceNgs2ChannelsCount::INVALID; + uint32_t sampleRate = 0; uint32_t configData; uint32_t frameOffset; uint32_t frameMargin; @@ -214,7 +214,6 @@ struct SceNgs2Handle_rack; struct SceNgs2Handle { SceNgs2HandleType const type; - SceNgs2WaveformInfo info; SceNgs2Handle(SceNgs2HandleType type): type(type) {} @@ -244,6 +243,7 @@ struct SceNgs2Handle_voice: public SceNgs2Handle { SceNgs2Handle_rack* parent; SceNgs2VoiceStateFlags state {}; + SceNgs2WaveformInfo info; Reader* reader = nullptr; // optional, depends on racktype From 79b1e532af79b74f5411b8b1df33ab4fcbff3a74 Mon Sep 17 00:00:00 2001 From: SysRay Date: Fri, 10 May 2024 10:24:49 +0200 Subject: [PATCH 09/19] ngs2| disable reading --- modules/libSceNgs2/entry.cpp | 42 +++++++++++++++++++------------- modules/libSceNgs2/readFuncs.cpp | 1 + 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/modules/libSceNgs2/entry.cpp b/modules/libSceNgs2/entry.cpp index 2ce34110..cc701411 100644 --- a/modules/libSceNgs2/entry.cpp +++ b/modules/libSceNgs2/entry.cpp @@ -27,25 +27,25 @@ int32_t _voiceControlWaveformBlock(SceNgs2Handle* voh, const SceNgs2SamplerVoice LOG_USE_MODULE(libSceNgs2); LOG_TRACE(L"waveblock: %d\n", svwfbp->numBlocks); - LOG_DEBUG(L"waveptr: %llx\n", svwfbp->data); + LOG_TRACE(L"waveptr: %llx\n", svwfbp->data); - if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; - auto voice = (SceNgs2Handle_voice*)voh; + // if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; + // auto voice = (SceNgs2Handle_voice*)voh; - if (voice->reader == nullptr) voice->reader = std::make_unique(voice).release(); + // if (voice->reader == nullptr) voice->reader = std::make_unique(voice).release(); - // svwfbp->data can be nullptr! - if (!voice->reader->init(svwfbp)) { - return Err::Ngs2::INVALID_WAVEFORM_DATA; - } + // // svwfbp->data can be nullptr! + // if (!voice->reader->init(svwfbp)) { + // return Err::Ngs2::INVALID_WAVEFORM_DATA; + // } - LOG_DEBUG(L"waveptr voice:0x%08llx %llx", (uint64_t)voh, svwfbp->data); + // LOG_DEBUG(L"waveptr voice:0x%08llx %llx", (uint64_t)voh, svwfbp->data); return Ok; } int32_t voiceControl_voice(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { LOG_USE_MODULE(libSceNgs2); - LOG_INFO(L"voiceControl_voice id:%u type:%u", phead->id & 0xFFFF, voh->type); + LOG_DEBUG(L"voiceControl_voice id:%u type:%u", phead->id & 0xFFFF, voh->type); if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; auto voice = (SceNgs2Handle_voice*)voh; @@ -76,7 +76,7 @@ int32_t voiceControl_voice(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phea int32_t voiceControl_mastering(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { LOG_USE_MODULE(libSceNgs2); - LOG_INFO(L"voiceControl_mastering id:%u type:%u", phead->id & 0xFFFF, voh->type); + LOG_DEBUG(L"voiceControl_mastering id:%u type:%u", phead->id & 0xFFFF, voh->type); switch ((SceNgs2MasteringParam)(phead->id & 0xFFFF)) { case SceNgs2MasteringParam::SETUP: { @@ -98,16 +98,21 @@ int32_t voiceControl_mastering(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* } int32_t voiceControl_reverb(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + LOG_USE_MODULE(libSceNgs2); + LOG_DEBUG(L"voice_reverbid:%u type:%u", phead->id & 0xFFFF, voh->type); return Ok; } int32_t voiceControl_equalizer(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + LOG_USE_MODULE(libSceNgs2); + LOG_DEBUG(L"voice_equalizer id:%u type:%u", phead->id & 0xFFFF, voh->type); + return Ok; } int32_t voiceControl_sampler(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { LOG_USE_MODULE(libSceNgs2); - LOG_INFO(L"voice_sampler id:%u type:%u", phead->id & 0xFFFF, voh->type); + LOG_DEBUG(L"voice_sampler id:%u type:%u", phead->id & 0xFFFF, voh->type); if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; @@ -145,6 +150,9 @@ int32_t voiceControl_sampler(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* ph } int32_t voiceControl_submixer(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* phead) { + LOG_USE_MODULE(libSceNgs2); + LOG_DEBUG(L"voice_submixer id:%u type:%u", phead->id & 0xFFFF, voh->type); + switch ((SceNgs2SubmixerParam)(phead->id & 0xFFFF)) { case SceNgs2SubmixerParam::SETUP: { } break; @@ -569,11 +577,11 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBu for (int32_t i = 0; i < count; i++) { if (rbi[i].bufferPtr != nullptr) { std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); - for (auto& voice: system->sampler->voices) { - if (voice.second.reader != nullptr) { - voice.second.reader->getAudio(&rbi[i]); - } - } + // for (auto& voice: system->sampler->voices) { + // if (voice.second.reader != nullptr) { + // voice.second.reader->getAudio(&rbi[i]); + // } + // } } } } diff --git a/modules/libSceNgs2/readFuncs.cpp b/modules/libSceNgs2/readFuncs.cpp index 2a998ae8..2073d840 100644 --- a/modules/libSceNgs2/readFuncs.cpp +++ b/modules/libSceNgs2/readFuncs.cpp @@ -112,6 +112,7 @@ int32_t parseRiffWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* user LOG_USE_MODULE(libSceNgs2); // Load headers and check magic + // todo use ffmeg, get the correct type (pcm, at9...) // Check if correct file RiffWaveHeader riffHeader; From 43b2e18c78579e8f898b03266075ea4c7aa5ea07 Mon Sep 17 00:00:00 2001 From: SysRay Date: Fri, 10 May 2024 10:32:09 +0200 Subject: [PATCH 10/19] cleanup --- modules/libSceNgs2/temp.txt | 34 ---------------------------------- 1 file changed, 34 deletions(-) delete mode 100644 modules/libSceNgs2/temp.txt diff --git a/modules/libSceNgs2/temp.txt b/modules/libSceNgs2/temp.txt deleted file mode 100644 index c1f7c8b6..00000000 --- a/modules/libSceNgs2/temp.txt +++ /dev/null @@ -1,34 +0,0 @@ -// create -result = sceNgs2SystemCreateWithAllocator(NULL, &allocator, &m_systemHandle); -result = sceNgs2RackCreateWithAllocator(m_systemHandle, SCE_NGS2_RACK_ID_MASTERING, NULL, &allocator, &m_masteringRackHandle); -result = sceNgs2RackCreateWithAllocator(m_systemHandle, SCE_NGS2_RACK_ID_SAMPLER, NULL, &allocator, &m_samplerRackHandle); - -// Voice : Audio source -sceNgs2RackGetVoiceHandle(m_samplerRackHandle, 0, &m_samplerVoiceHandle); -sceNgs2SamplerVoiceSetup(m_samplerVoiceHandle, &m_waveformInfo.format, 0); -sceNgs2SamplerVoiceAddWaveformBlocks(m_samplerVoiceHandle, m_waveformData, m_waveformInfo.aBlock, m_waveformInfo.numBlocks, 0); -sceNgs2VoicePatch(m_samplerVoiceHandle, 0, m_masteringVoiceHandle, 0); - -result = sceNgs2VoiceKickEvent(m_samplerVoiceHandle, SCE_NGS2_VOICE_EVENT_PLAY); // sceNgs2VoiceControl - - - -// ### Read Wave -result = fileLoad(WAVEFORM_PATH, &m_waveformData, &m_waveformDataSize); -if (result < SCE_OK) { - goto failed; -} - -result = sceNgs2ParseWaveformData(m_waveformData, m_waveformDataSize, &m_waveformInfo); -if (result < 0) { - goto failed; -} -// --- - -sceNgs2RackGetVoiceHandle(m_samplerRackHandle, 0, &m_samplerVoiceHandle); -sceNgs2SamplerVoiceSetup(m_samplerVoiceHandle, &m_waveformInfo.format, 0); -sceNgs2SamplerVoiceAddWaveformBlocks(m_samplerVoiceHandle, m_waveformData, m_waveformInfo.aBlock, m_waveformInfo.numBlocks, 0); -sceNgs2VoicePatch(m_samplerVoiceHandle, 0, m_masteringVoiceHandle, 0); - - -sceNgs2SystemRender() // takes data \ No newline at end of file From 2771f6f4a7cf8156cf5e917e9bb61736b081e2a9 Mon Sep 17 00:00:00 2001 From: SysRay Date: Tue, 14 May 2024 22:58:36 +0200 Subject: [PATCH 11/19] directMem| fix reserve and getAvailableSize --- core/dmem/types/directmem.cpp | 44 ++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/core/dmem/types/directmem.cpp b/core/dmem/types/directmem.cpp index ec5947ab..c135cdf5 100644 --- a/core/dmem/types/directmem.cpp +++ b/core/dmem/types/directmem.cpp @@ -255,7 +255,7 @@ int DirectMemory::free(off_t start, size_t len) { return Ok; } - if (itHeap->first != addr || itHeap->second.size != len) { + if (len != 0 && (itHeap->first != addr || itHeap->second.size != len)) { LOG_ERR(L"free Error| start:0x%08llx len:0x%08llx != start:0x%08llx len:0x%08llx", addr, len, itHeap->first, itHeap->second.size); } @@ -313,8 +313,9 @@ int DirectMemory::map(uint64_t vaddr, off_t offset, size_t len, int prot, int fl MemoryInfo* info = nullptr; if (flags & (int)filesystem::SceMapMode::FIXED) { for (auto& item: m_objects) { - if (item.second.state == MemoryState::Reserved && item.first <= vaddr && (item.first + item.second.size) > (vaddr + len)) { - info = &item.second; + if (item.second.state == MemoryState::Reserved && item.first <= vaddr && item.second.size >= len) { + info = &item.second; + desVaddr = info->addr; } } } @@ -324,7 +325,7 @@ int DirectMemory::map(uint64_t vaddr, off_t offset, size_t len, int prot, int fl // - // Check if Commit needed - if (info->state == MemoryState::Free) { + if (info->state == MemoryState::Free || info->state == MemoryState::Reserved) { MEM_ADDRESS_REQUIREMENTS addressReqs = {0}; MEM_EXTENDED_PARAMETER extendedParams = {0}; @@ -335,8 +336,11 @@ int DirectMemory::map(uint64_t vaddr, off_t offset, size_t len, int prot, int fl extendedParams.Type = MemExtendedParameterAddressRequirements; extendedParams.Pointer = &addressReqs; - void* ptr = VirtualAlloc2(NULL, (void*)desVaddr, info->size, MEM_RESERVE | MEM_COMMIT | MEM_WRITE_WATCH, convProtection(prot), - desVaddr != 0 ? 0 : &extendedParams, desVaddr != 0 ? 0 : 1); + uint32_t flags = MEM_COMMIT; + if (info->state != MemoryState::Reserved) { + flags |= MEM_RESERVE | MEM_WRITE_WATCH; + } + void* ptr = VirtualAlloc2(NULL, (void*)desVaddr, info->size, flags, convProtection(prot), desVaddr != 0 ? 0 : &extendedParams, desVaddr != 0 ? 0 : 1); if (ptr == 0) { auto const err = GetLastError(); LOG_ERR(L"Commit Error| addr:0x%08llx len:0x%08llx err:%d", info->addr, info->size, GetLastError()); @@ -432,10 +436,32 @@ uint64_t DirectMemory::size() const { int DirectMemory::getAvailableSize(uint32_t start, uint32_t end, size_t alignment, uint32_t* startOut, size_t* sizeOut) const { LOG_USE_MODULE(DirectMemory); - LOG_DEBUG(L"availableSize: start:0x%08llx end:0x%08llx alignment:0x%08llx", start, end, alignment); + LOG_DEBUG(L"availableSize: start:0x%lx end:0x%lx alignment:0x%08llx", start, end, alignment); + + auto itItem = m_objects.lower_bound(DIRECTMEM_START + start); + if (m_objects.empty() || itItem == m_objects.end()) { + *startOut = start; + *sizeOut = std::min(SCE_KERNEL_MAIN_DMEM_SIZE, (uint64_t)end - start); + return Ok; + } + + *startOut = start; + *sizeOut = (itItem->second.addr - DIRECTMEM_START) - start; + // if (itItem->second.addr + itItem->second.size >= DIRECTMEM_START + end) { + // *startOut = end; + // *sizeOut = 0; + // return Ok; + // } + + // *startOut = start; + // *sizeOut = 0; + + // auto itEnd = m_objects.lower_bound(DIRECTMEM_START + end); + // for (; itItem != itEnd; ++itItem) { + // *startOut = (itItem->second.addr + itItem->second.size) - DIRECTMEM_START; + // } - *startOut = m_usedSize; - *sizeOut = SCE_KERNEL_MAIN_DMEM_SIZE - m_usedSize; + // if (*startOut > end) *sizeOut = end - *startOut; return Ok; } From 9a3dbd08395be7840b7f722a827b0de9c4985147 Mon Sep 17 00:00:00 2001 From: SysRay Date: Tue, 14 May 2024 22:59:21 +0200 Subject: [PATCH 12/19] ngs2| dump --- modules/libSceNgs2/entry.cpp | 41 ++-- modules/libSceNgs2/readFuncs.cpp | 57 ++--- modules/libSceNgs2/readFuncs.h | 8 +- modules/libSceNgs2/reader.cpp | 360 +++++++++++++++++++++---------- modules/libSceNgs2/reader.h | 17 +- modules/libSceNgs2/types.h | 20 ++ 6 files changed, 328 insertions(+), 175 deletions(-) diff --git a/modules/libSceNgs2/entry.cpp b/modules/libSceNgs2/entry.cpp index cc701411..3c1c5411 100644 --- a/modules/libSceNgs2/entry.cpp +++ b/modules/libSceNgs2/entry.cpp @@ -29,17 +29,17 @@ int32_t _voiceControlWaveformBlock(SceNgs2Handle* voh, const SceNgs2SamplerVoice LOG_TRACE(L"waveblock: %d\n", svwfbp->numBlocks); LOG_TRACE(L"waveptr: %llx\n", svwfbp->data); - // if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; - // auto voice = (SceNgs2Handle_voice*)voh; + if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; + auto voice = (SceNgs2Handle_voice*)voh; - // if (voice->reader == nullptr) voice->reader = std::make_unique(voice).release(); + if (voice->reader == nullptr) voice->reader = std::make_unique(voice).release(); - // // svwfbp->data can be nullptr! - // if (!voice->reader->init(svwfbp)) { - // return Err::Ngs2::INVALID_WAVEFORM_DATA; - // } + // svwfbp->data can be nullptr! + if (!voice->reader->init(svwfbp)) { + return Err::Ngs2::INVALID_WAVEFORM_DATA; + } - // LOG_DEBUG(L"waveptr voice:0x%08llx %llx", (uint64_t)voh, svwfbp->data); + LOG_DEBUG(L"waveptr voice:0x%08llx %llx", (uint64_t)voh, svwfbp->data); return Ok; } @@ -125,8 +125,10 @@ int32_t voiceControl_sampler(SceNgs2Handle* voh, const SceNgs2VoiceParamHead* ph } break; case SceNgs2SamplerParam::ADD_WAVEFORM_BLOCKS: { return _voiceControlWaveformBlock(voh, (const SceNgs2SamplerVoiceWaveformBlocksParam*)phead); - } break; + } case SceNgs2SamplerParam::REPLACE_WAVEFORM_ADDRESS: { + auto item = (SceNgs2CustomSamplerVoiceWaveformAddressParam*)phead; + if (voice->reader != nullptr) voice->reader->setNewData(item->pDataStart, item->pDataEnd); } break; case SceNgs2SamplerParam::SET_WAVEFORM_FRAME_OFFSET: { } break; @@ -563,7 +565,7 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBu if (rbi->waveType >= SceNgs2WaveFormType::MAX_TYPES) return Err::Ngs2::INVALID_WAVEFORM_TYPE; if (rbi->channelsCount > SceNgs2ChannelsCount::CH_7_1) return Err::Ngs2::INVALID_NUM_CHANNELS; - // uint32_t const numSamples = rbi->bufferSize / ((uint32_t)rbi->channelsCount * getSampleBytes(rbi->waveType)); + uint32_t const numSamples = rbi->bufferSize / ((uint32_t)rbi->channelsCount * getSampleBytes(rbi->waveType)); if (system->sampler == nullptr) { // @@ -577,11 +579,11 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBu for (int32_t i = 0; i < count; i++) { if (rbi[i].bufferPtr != nullptr) { std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); - // for (auto& voice: system->sampler->voices) { - // if (voice.second.reader != nullptr) { - // voice.second.reader->getAudio(&rbi[i]); - // } - // } + for (auto& voice: system->sampler->voices) { + if (voice.second.reader != nullptr) { + // voice.second.reader->getAudio(&rbi[i], numSamples); + } + } } } } @@ -664,7 +666,14 @@ EXPORT SYSV_ABI int32_t sceNgs2VoiceGetState(SceNgs2Handle* voh, SceNgs2VoiceSta if (auto it = pimpl->handles.find(voh); it == pimpl->handles.end()) return Err::Ngs2::INVALID_VOICE_HANDLE; if (voh->type != SceNgs2HandleType::Voice) return Err::Ngs2::INVALID_VOICE_HANDLE; - auto voice = (SceNgs2Handle_voice*)voh; + auto voice = (SceNgs2Handle_voice*)voh; + if (voice->reader != nullptr) { + if (size != sizeof(SceNgs2SamplerVoiceState)) return getErr(ErrCode::_EINVAL); + + voice->reader->getState((SceNgs2SamplerVoiceState*)state); + return Ok; + } + state->stateFlags = voice->state.data; // LOG_DEBUG(L"state voice:0x%08llx state:%x", (uint64_t)voh, state->stateFlags); diff --git a/modules/libSceNgs2/readFuncs.cpp b/modules/libSceNgs2/readFuncs.cpp index 2073d840..e72390e1 100644 --- a/modules/libSceNgs2/readFuncs.cpp +++ b/modules/libSceNgs2/readFuncs.cpp @@ -46,42 +46,29 @@ static SceNgs2WaveFormType convWaveType(AVCodecID codec) { } // namespace int readFunc_linearBuffer(void* userData_, uint8_t* buf, int size) { - auto userData = (userData_inerBuffer*)userData_; + auto rb = (userData_inerBuffer*)userData_; - int64_t const dataLeft = (int64_t)userData->size - (int64_t)userData->curOffset; - - auto readSize = std::min(dataLeft, (int64_t)size); - - if (readSize > 0) { - ::memcpy(buf, (uint8_t*)userData->ptr + userData->curOffset, readSize); - userData->curOffset += readSize; - return readSize; - } - - userData->curOffset = 0; // reset it - return -1; + auto len = std::min(int(rb->size - rb->curOffset), size); + if (len == 0) return AVERROR_EOF; + ::memcpy(buf, (uint8_t*)rb->ptr + rb->curOffset, len); + rb->curOffset += len; + return len; } -int64_t seekFunc_linearBuffer(void* userData_, int64_t offset, int whence) { - auto userData = (userData_inerBuffer*)userData_; +int64_t seekFunc_linearBuffer(void* userData_, int64_t pos, int whence) { + auto rb = (userData_inerBuffer*)userData_; - if ((whence & AVSEEK_SIZE) > 0) { - // return size (0 on not avail) - return userData->size; - } + if (whence == AVSEEK_SIZE) return rb->size; - switch ((std::ios_base::seekdir)(whence & 0xff)) { - case std::ios_base::beg: userData->curOffset = offset; break; - case std::ios_base::cur: - if (userData->curOffset < offset) - userData->curOffset = 0; - else - userData->curOffset += offset; - break; - case std::ios_base::end: userData->curOffset = std::min(userData->size, userData->size + offset); break; + if (whence == SEEK_SET) { + rb->curOffset = pos; + } else if (whence == SEEK_CUR) { + rb->curOffset += pos; + } else if (whence == SEEK_END) { + rb->curOffset = rb->size - pos; } - return userData->curOffset; + return rb->curOffset; } int readFunc_file(void* userData_, uint8_t* buf, int size) { @@ -195,26 +182,26 @@ int32_t parseRiffWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* user return Ok; } -std::optional convChannelLayout(SceNgs2ChannelsCount count) { +AVChannelLayout convChannelLayout(SceNgs2ChannelsCount count) { LOG_USE_MODULE(libSceNgs2); switch (count) { case SceNgs2ChannelsCount::CH_1_0: { - return {AV_CHANNEL_LAYOUT_MONO}; + return AV_CHANNEL_LAYOUT_MONO; } break; case SceNgs2ChannelsCount::CH_2_0: { - return {AV_CHANNEL_LAYOUT_STEREO}; + return AV_CHANNEL_LAYOUT_STEREO; } break; case SceNgs2ChannelsCount::CH_5_1: { - return {AV_CHANNEL_LAYOUT_5POINT1}; + return AV_CHANNEL_LAYOUT_5POINT1; } break; case SceNgs2ChannelsCount::CH_7_1: { - return {AV_CHANNEL_LAYOUT_CUBE}; + return AV_CHANNEL_LAYOUT_CUBE; } break; default: { LOG_ERR(L"channel layout not set"); } break; } - return std::nullopt; + return AV_CHANNEL_LAYOUT_MASK(1, AV_CHANNEL_ORDER_UNSPEC); } uint32_t getSampleBytes(SceNgs2WaveFormType type) { diff --git a/modules/libSceNgs2/readFuncs.h b/modules/libSceNgs2/readFuncs.h index 5049fd92..2477f794 100644 --- a/modules/libSceNgs2/readFuncs.h +++ b/modules/libSceNgs2/readFuncs.h @@ -1,8 +1,6 @@ #pragma once #include "types.h" -#include - using funcReadBuf_t = int (*)(void*, uint8_t*, int); using funcSeekBuf_t = int64_t (*)(void*, int64_t, int); @@ -27,6 +25,6 @@ int64_t seekFunc_user(void* userData_, int64_t offset, int whence); int32_t parseRiffWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData, SceNgs2WaveformFormat* wf); -std::optional convChannelLayout(SceNgs2ChannelsCount); - -uint32_t getSampleBytes(SceNgs2WaveFormType); \ No newline at end of file +struct AVChannelLayout; +AVChannelLayout convChannelLayout(SceNgs2ChannelsCount); +uint32_t getSampleBytes(SceNgs2WaveFormType); \ No newline at end of file diff --git a/modules/libSceNgs2/reader.cpp b/modules/libSceNgs2/reader.cpp index 0b3edca9..59afe218 100644 --- a/modules/libSceNgs2/reader.cpp +++ b/modules/libSceNgs2/reader.cpp @@ -18,24 +18,52 @@ LOG_DEFINE_MODULE(libSceNgs2); namespace { -AVSampleFormat convFormat(SceNgs2WaveFormType type) { +std::pair convFormat(SceNgs2WaveFormType type) { switch (type) { - case SceNgs2WaveFormType::PCM_U8: return AVSampleFormat::AV_SAMPLE_FMT_U8; - case SceNgs2WaveFormType::PCM_I16LITTLE: return AVSampleFormat::AV_SAMPLE_FMT_S16; - case SceNgs2WaveFormType::PCM_I16BIG: return AVSampleFormat::AV_SAMPLE_FMT_S16; - case SceNgs2WaveFormType::PCM_I24LITTLE: return AVSampleFormat::AV_SAMPLE_FMT_NONE; - case SceNgs2WaveFormType::PCM_I24BIG: return AVSampleFormat::AV_SAMPLE_FMT_NONE; - case SceNgs2WaveFormType::PCM_I32LITTLE: return AVSampleFormat::AV_SAMPLE_FMT_S32; - case SceNgs2WaveFormType::PCM_I32BIG: return AVSampleFormat::AV_SAMPLE_FMT_S32; - case SceNgs2WaveFormType::PCM_F32LITTLE: return AVSampleFormat::AV_SAMPLE_FMT_FLT; - case SceNgs2WaveFormType::PCM_F32BIG: return AVSampleFormat::AV_SAMPLE_FMT_FLT; - case SceNgs2WaveFormType::PCM_F64LITTLE: return AVSampleFormat::AV_SAMPLE_FMT_DBL; - case SceNgs2WaveFormType::PCM_F64BIG: return AVSampleFormat::AV_SAMPLE_FMT_DBL; - case SceNgs2WaveFormType::VAG: return AVSampleFormat::AV_SAMPLE_FMT_FLT; // todo - case SceNgs2WaveFormType::ATRAC9: return AVSampleFormat::AV_SAMPLE_FMT_FLT; // todo + case SceNgs2WaveFormType::PCM_U8: return {AVSampleFormat::AV_SAMPLE_FMT_U8, 1}; + case SceNgs2WaveFormType::PCM_I16LITTLE: return {AVSampleFormat::AV_SAMPLE_FMT_S16, 2}; + case SceNgs2WaveFormType::PCM_I16BIG: return {AVSampleFormat::AV_SAMPLE_FMT_S16, 2}; + case SceNgs2WaveFormType::PCM_I24LITTLE: return {AVSampleFormat::AV_SAMPLE_FMT_NONE, 3}; + case SceNgs2WaveFormType::PCM_I24BIG: return {AVSampleFormat::AV_SAMPLE_FMT_NONE, 3}; + case SceNgs2WaveFormType::PCM_I32LITTLE: return {AVSampleFormat::AV_SAMPLE_FMT_S32, 4}; + case SceNgs2WaveFormType::PCM_I32BIG: return {AVSampleFormat::AV_SAMPLE_FMT_S32, 4}; + case SceNgs2WaveFormType::PCM_F32LITTLE: return {AVSampleFormat::AV_SAMPLE_FMT_FLT, 4}; + case SceNgs2WaveFormType::PCM_F32BIG: return {AVSampleFormat::AV_SAMPLE_FMT_FLT, 4}; + case SceNgs2WaveFormType::PCM_F64LITTLE: return {AVSampleFormat::AV_SAMPLE_FMT_DBL, 8}; + case SceNgs2WaveFormType::PCM_F64BIG: return {AVSampleFormat::AV_SAMPLE_FMT_DBL, 8}; + case SceNgs2WaveFormType::VAG: return {AVSampleFormat::AV_SAMPLE_FMT_FLT, 4}; + case SceNgs2WaveFormType::ATRAC9: return {AVSampleFormat::AV_SAMPLE_FMT_FLT, 4}; default: break; } - return AVSampleFormat::AV_SAMPLE_FMT_NONE; + return {AVSampleFormat::AV_SAMPLE_FMT_NONE, 0}; +} + +std::pair convFormatPlanar(SceNgs2WaveFormType type) { + switch (type) { + case SceNgs2WaveFormType::PCM_U8: return {AVSampleFormat::AV_SAMPLE_FMT_U8P, 1}; + case SceNgs2WaveFormType::PCM_I16LITTLE: return {AVSampleFormat::AV_SAMPLE_FMT_S16P, 2}; + case SceNgs2WaveFormType::PCM_I16BIG: return {AVSampleFormat::AV_SAMPLE_FMT_S16P, 2}; + case SceNgs2WaveFormType::PCM_I24LITTLE: return {AVSampleFormat::AV_SAMPLE_FMT_NONE, 3}; + case SceNgs2WaveFormType::PCM_I24BIG: return {AVSampleFormat::AV_SAMPLE_FMT_NONE, 3}; + case SceNgs2WaveFormType::PCM_I32LITTLE: return {AVSampleFormat::AV_SAMPLE_FMT_S32P, 4}; + case SceNgs2WaveFormType::PCM_I32BIG: return {AVSampleFormat::AV_SAMPLE_FMT_S32P, 4}; + case SceNgs2WaveFormType::PCM_F32LITTLE: return {AVSampleFormat::AV_SAMPLE_FMT_FLTP, 4}; + case SceNgs2WaveFormType::PCM_F32BIG: return {AVSampleFormat::AV_SAMPLE_FMT_FLTP, 4}; + case SceNgs2WaveFormType::PCM_F64LITTLE: return {AVSampleFormat::AV_SAMPLE_FMT_DBLP, 8}; + case SceNgs2WaveFormType::PCM_F64BIG: return {AVSampleFormat::AV_SAMPLE_FMT_DBLP, 8}; + case SceNgs2WaveFormType::VAG: return {AVSampleFormat::AV_SAMPLE_FMT_FLTP, 4}; + case SceNgs2WaveFormType::ATRAC9: return {AVSampleFormat::AV_SAMPLE_FMT_FLTP, 4}; + default: break; + } + return {AVSampleFormat::AV_SAMPLE_FMT_NONE, 0}; +} + +constexpr bool operator==(AVChannelLayout const& rhs, AVChannelLayout const& lhs) { + return rhs.nb_channels == lhs.nb_channels && rhs.u.mask == lhs.u.mask; +} + +constexpr bool operator!=(AVChannelLayout const& rhs, AVChannelLayout const& lhs) { + return !(rhs == lhs); } struct PImpl { @@ -59,7 +87,11 @@ struct PImpl { bool newPacket = true; SwrContext* swrCtx = nullptr; + + AVChannelLayout curChannelLayoutIn; + AVChannelLayout curChannelLayoutOut; }; + } // namespace Reader::Reader(SceNgs2Handle_voice* voice): voice(voice) { @@ -72,16 +104,12 @@ Reader::~Reader() { bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { LOG_USE_MODULE(libSceNgs2); - if (m_isInit) return true; // todo auto pimpl = (PImpl*)m_pimpl; if (param->data == nullptr) { // Reset voice->state.bits.Empty = true; - - delete pimpl; - m_pimpl = std::make_unique().release(); return true; } m_isInit = false; @@ -90,6 +118,19 @@ bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { pimpl->block = param->aBlock[0]; pimpl->curOffset = 0; + // m_state.numDecodedSamples = 0; + // m_state.decodedDataSize = 0; + + if (voice->info.type != SceNgs2WaveFormType::ATRAC9 && voice->info.type != SceNgs2WaveFormType::VAG) { + m_isCompressed = false; + m_isInit = true; + + voice->state.bits.Empty = false; + return true; + } + + return false; + // Check if riff or uncompressed auto riffHeader = (RiffWaveHeader const*)param->data; if (memcmp(riffHeader->chunkID, "RIFF", 4) != 0 || memcmp(riffHeader->riffType, "WAVE", 4) != 0) { @@ -120,10 +161,10 @@ bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { // Open the input pimpl->fmtctx = avformat_alloc_context(); - pimpl->fmtctx->pb = avioctx; - pimpl->fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; + // pimpl->fmtctx->pb = avioctx; + // pimpl->fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; - int ret = avformat_open_input(&pimpl->fmtctx, nullptr, nullptr, nullptr); + int ret = avformat_open_input(&pimpl->fmtctx, "F:/down2/atrac9mem/snd0.at9", nullptr, nullptr); if (ret != 0) { LOG_ERR(L"Reader: ffmpeg failed to read passed data: %d", ret); return false; @@ -135,9 +176,15 @@ bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { LOG_ERR(L"avformat_find_stream_info result:%d", res); return false; } + for (auto i = 0; i < pimpl->fmtctx->nb_streams; ++i) { + if (pimpl->fmtctx->streams[i]->codecpar->codec_type == AVMediaType::AVMEDIA_TYPE_AUDIO) { + pimpl->astream = pimpl->fmtctx->streams[i]; + pimpl->stream_idx = i; + break; + } + } - pimpl->stream_idx = av_find_best_stream(pimpl->fmtctx, AVMEDIA_TYPE_AUDIO, -1, -1, &pimpl->codec, 0); - pimpl->astream = pimpl->fmtctx->streams[pimpl->stream_idx]; + pimpl->codec = avcodec_find_decoder(pimpl->astream->codecpar->codec_id); pimpl->codecContext = avcodec_alloc_context3(pimpl->codec); if (auto err = avcodec_parameters_to_context(pimpl->codecContext, pimpl->astream->codecpar); err != 0) { @@ -171,44 +218,39 @@ bool Reader::init(SceNgs2SamplerVoiceWaveformBlocksParam const* param) { return true; } -bool Reader::getAudioUncompressed(SceNgs2RenderBufferInfo* rbi) { +void Reader::setNewData(void const* start, void const* end) { + LOG_USE_MODULE(libSceNgs2); auto pimpl = (PImpl*)m_pimpl; - // Check repeat - if (pimpl->block.size <= pimpl->curOffset) { - if (pimpl->block.numRepeat > 0) { - pimpl->curOffset = 0; - --pimpl->block.numRepeat; - } else { - voice->state.bits.Empty = true; - return false; - } - } - // - - - uint32_t const readSize = std::min(rbi->bufferSize, (size_t)pimpl->block.size - pimpl->curOffset); - - std::memcpy(rbi->bufferPtr, pimpl->data + pimpl->curOffset, readSize); - pimpl->curOffset += readSize; + pimpl->curOffset = 0; + pimpl->data = (uint8_t const*)start; + pimpl->block.size = (uint64_t)end - (uint64_t)start; - return true; + voice->state.bits.Empty = false; } -bool Reader::getAudioCompressed(SceNgs2RenderBufferInfo* rbi) { +bool Reader::getAudioUncompressed(SceNgs2RenderBufferInfo* rbi, uint32_t numOutSamples) { LOG_USE_MODULE(libSceNgs2); - auto pimpl = (PImpl*)m_pimpl; - if (pimpl->swrCtx == nullptr) { - auto optDstChLayout = convChannelLayout(rbi->channelsCount); - if (!optDstChLayout) { + auto const channelLayoutOut = convChannelLayout(rbi->channelsCount); + auto const channelLayoutIn = convChannelLayout(voice->info.channelsCount); + + if (pimpl->swrCtx == nullptr || channelLayoutOut != pimpl->curChannelLayoutOut || channelLayoutIn != pimpl->curChannelLayoutIn) { + pimpl->curChannelLayoutOut = convChannelLayout(rbi->channelsCount); + pimpl->curChannelLayoutIn = convChannelLayout(voice->info.channelsCount); + if (pimpl->curChannelLayoutOut.order == AV_CHANNEL_ORDER_UNSPEC || pimpl->curChannelLayoutIn.order == AV_CHANNEL_ORDER_UNSPEC) { return false; } - auto format = convFormat(rbi->waveType); - if (format == AVSampleFormat::AV_SAMPLE_FMT_NONE) return false; - if (swr_alloc_set_opts2(&pimpl->swrCtx, &(*optDstChLayout), format, voice->info.sampleRate, &pimpl->codecContext->ch_layout, - pimpl->codecContext->sample_fmt, pimpl->codecContext->sample_rate, 0, NULL)) { + auto const [formatOut, bytesOut] = convFormatPlanar(rbi->waveType); + if (formatOut == AVSampleFormat::AV_SAMPLE_FMT_NONE) return false; + + auto const [formatIn, bytesIn] = convFormatPlanar(voice->info.type); + if (formatIn == AVSampleFormat::AV_SAMPLE_FMT_NONE) return false; + + if (swr_alloc_set_opts2(&pimpl->swrCtx, &pimpl->curChannelLayoutOut, formatOut, 48000, &pimpl->curChannelLayoutIn, formatIn, voice->info.sampleRate, 0, + NULL)) { LOG_ERR(L"Reader:Couldn't alloc swr"); return false; } @@ -217,90 +259,180 @@ bool Reader::getAudioCompressed(SceNgs2RenderBufferInfo* rbi) { pimpl->cleanup.emplace_back([&] { swr_free(&pimpl->swrCtx); }); } - size_t offset = 0; - - while (offset < rbi->bufferSize) { - // Get a new packet - if (pimpl->newPacket) { - pimpl->packet->dts = AV_NOPTS_VALUE; - pimpl->packet->pts = AV_NOPTS_VALUE; - - int state = av_read_frame(pimpl->fmtctx, pimpl->packet); - if (state < 0) { - if (state != AVERROR_EOF) { - LOG_ERR(L"av_read_frame error %d", state); - } else { - voice->state.bits.Empty = true; - voice->state.bits.Playing = false; - } - return false; - } - - // Skip if not a audio packet - if (pimpl->packet->stream_index != pimpl->stream_idx) { - continue; - } - - pimpl->newPacket = false; - } - // - - - // Process packet - if (int ret = avcodec_send_packet(pimpl->codecContext, pimpl->packet); ret < 0) { - if (ret == AVERROR(EAGAIN)) { - av_packet_unref(pimpl->packet); - pimpl->newPacket = true; - continue; // Get new frame - } else if (ret == AVERROR_EOF) { - voice->state.bits.Empty = true; - } else { - voice->state.bits.Error = true; - } - voice->state.bits.Playing = false; + // Check repeat + if (pimpl->block.size <= pimpl->curOffset) { + if (pimpl->block.numRepeat > 0) { + pimpl->curOffset = 0; + --pimpl->block.numRepeat; + } else { + voice->state.data = 0; + voice->state.bits.Empty = true; return false; } + } + // - - av_packet_unref(pimpl->packet); - //- packet + uint32_t const readSize = std::min(rbi->bufferSize, (size_t)pimpl->block.size - pimpl->curOffset); - // Now the frames - auto const retRecv = avcodec_receive_frame(pimpl->codecContext, pimpl->frame); + auto const [formatIn, bytesIn] = convFormatPlanar(voice->info.type); + auto const [formatOut, bytesOut] = convFormatPlanar(rbi->waveType); - int outNumSamples = swr_get_out_samples(pimpl->swrCtx, pimpl->frame->nb_samples); + std::vector audioBuffers(((int)rbi->channelsCount)); - // todo get sample size, nb_channels is zero (fix) - uint8_t* audioBuffers[1] = {&((uint8_t*)rbi->bufferPtr)[offset]}; + auto const channelSizeOut = numOutSamples * bytesOut; + for (uint8_t n = 0; n < audioBuffers.size(); ++n) { + audioBuffers[n] = &((uint8_t*)rbi->bufferPtr)[n * channelSizeOut]; + } - if (outNumSamples = swr_convert(pimpl->swrCtx, audioBuffers, outNumSamples, (uint8_t const**)pimpl->frame->data, pimpl->frame->nb_samples); - outNumSamples < 0) { - LOG_WARN(L"swr_convert"); - } + if (pimpl->block.numSamples > 0) { + std::vector audioBuffersIn(((int)voice->info.channelsCount)); - av_frame_unref(pimpl->frame); - // - + for (uint8_t n = 0; n < audioBuffersIn.size(); ++n) { + audioBuffersIn[n] = &((uint8_t*)pimpl->data)[pimpl->curOffset + n * pimpl->block.numSamples]; + } - auto const bufferSize_ = (uint32_t)rbi->channelsCount * outNumSamples * av_get_bytes_per_sample(convFormat(rbi->waveType)); + auto numSamples = swr_convert(pimpl->swrCtx, audioBuffers.data(), numOutSamples, audioBuffersIn.data(), pimpl->block.numSamples); + pimpl->block.numSamples = 0; + } else { + std::vector audioBuffersIn(((int)voice->info.channelsCount)); + audioBuffersIn[0] = &((uint8_t*)pimpl->data)[pimpl->curOffset]; - // float* samples = (float*)(&((uint8_t*)rbi->bufferPtr)[offset]); - // for (int i = 0; i < outNumSamples * (int)rbi->channelsCount; i++) { - // samples[i] *= 100000.0; - // } + auto numSamples = swr_convert(pimpl->swrCtx, audioBuffers.data(), numOutSamples, nullptr, 0); + if (numSamples == 0) { + m_state.numDecodedSamples += pimpl->block.numSamples; + m_state.decodedDataSize += pimpl->block.size; + voice->state.bits.Empty = true; - offset += bufferSize_; + pimpl->curOffset = pimpl->block.size; + return false; + } } + + return true; +} + +bool Reader::getAudioCompressed(SceNgs2RenderBufferInfo* rbi) { + LOG_USE_MODULE(libSceNgs2); + + auto pimpl = (PImpl*)m_pimpl; + + // if (pimpl->swrCtx == nullptr) { + // auto optDstChLayout = convChannelLayout(rbi->channelsCount); + // if (!optDstChLayout) { + // return false; + // } + // auto const [format, bytesOut] = convFormat(rbi->waveType); + // if (format == AVSampleFormat::AV_SAMPLE_FMT_NONE) return false; + + // if (swr_alloc_set_opts2(&pimpl->swrCtx, &(*optDstChLayout), format, voice->info.sampleRate, &pimpl->codecContext->ch_layout, + // pimpl->codecContext->sample_fmt, pimpl->codecContext->sample_rate, 0, NULL)) { + // LOG_ERR(L"Reader:Couldn't alloc swr"); + // return false; + // } + + // swr_init(pimpl->swrCtx); + // pimpl->cleanup.emplace_back([&] { swr_free(&pimpl->swrCtx); }); + // } + + // size_t offset = 0; + + // while (offset < rbi->bufferSize) { + // // Get a new packet + // if (pimpl->newPacket) { + // pimpl->packet->dts = AV_NOPTS_VALUE; + // pimpl->packet->pts = AV_NOPTS_VALUE; + + // int state = av_read_frame(pimpl->fmtctx, pimpl->packet); + // if (state < 0) { + // if (state != AVERROR_EOF) { + // LOG_ERR(L"av_read_frame error %d", state); + // } else { + // voice->state.bits.Empty = true; + // } + // return false; + // } + + // // Skip if not a audio packet + // if (pimpl->packet->stream_index != pimpl->stream_idx) { + // continue; + // } + + // pimpl->newPacket = false; + // } + // // - + + // // Process packet + // if (int ret = avcodec_send_packet(pimpl->codecContext, pimpl->packet); ret < 0) { + // if (ret == AVERROR(EAGAIN)) { + // av_packet_unref(pimpl->packet); + // pimpl->newPacket = true; + // continue; // Get new frame + // } else if (ret == AVERROR_EOF) { + // voice->state.bits.Empty = true; + // } else { + // voice->state.bits.Error = true; + // } + + // return false; + // } + + // av_packet_unref(pimpl->packet); + // //- packet + + // // Now the frames + // auto const retRecv = avcodec_receive_frame(pimpl->codecContext, pimpl->frame); + + // int outNumSamples = swr_get_out_samples(pimpl->swrCtx, pimpl->frame->nb_samples); + + // // todo get sample size, nb_channels is zero (fix) + // auto const [format, bytesOut] = convFormat(rbi->waveType); + // auto const channelSize = (uint32_t)outNumSamples * av_get_bytes_per_sample(format); + + // std::vector audioBuffers(((int)rbi->channelsCount)); + // for (uint8_t n = 0; n < audioBuffers.size(); ++n) { + // audioBuffers[n] = &((uint8_t*)rbi->bufferPtr)[offset + n * channelSize]; + // } + + // for (int i = 0; i < rbi->bufferSize / 4; ++i) { // Filling the chanels with data + // // We should fill all the channels with available data, it seems. + // // The sound plays slightly quieter if we fill only two first channels. + // ((float*)rbi->bufferPtr)[offset + i] = ((float*)pimpl->frame->data[i % pimpl->frame->ch_layout.nb_channels])[i / (int)rbi->channelsCount]; + // } + + // // uint8_t* audioBuffers[8] = {&((uint8_t*)rbi->bufferPtr)[offset], &((uint8_t*)rbi->bufferPtr)[offset], + // // &((uint8_t*)rbi->bufferPtr)[offset],&((uint8_t*)rbi->bufferPtr)[offset],&((uint8_t*)rbi->bufferPtr)[offset],&((uint8_t*)rbi->bufferPtr)[offset],}; + + // // if (outNumSamples = swr_convert(pimpl->swrCtx, audioBuffers.data(), outNumSamples, (uint8_t const**)pimpl->frame->extended_data, + // // pimpl->frame->nb_samples); + // // outNumSamples < 0) { + // // LOG_WARN(L"swr_convert"); + // // } + + // av_frame_unref(pimpl->frame); + // // - + + // auto const bufferSize_ = (uint32_t)rbi->channelsCount * channelSize; + + // // float* samples = (float*)(&((uint8_t*)rbi->bufferPtr)[offset]); + // // for (int i = 0; i < outNumSamples * (int)rbi->channelsCount; i++) { + // // samples[i] *= 100000.0; + // // } + + // offset += (uint32_t)rbi->channelsCount * channelSize; + // } return true; } -bool Reader::getAudio(SceNgs2RenderBufferInfo* rbi) { - if (m_isInit == false || !voice->state.bits.Playing || (voice->state.bits.Playing && voice->state.bits.Paused)) { +bool Reader::getAudio(SceNgs2RenderBufferInfo* rbi, uint32_t numOutSamples) { + if (m_isInit == false || voice->state.bits.Empty || !voice->state.bits.Playing || (voice->state.bits.Playing && voice->state.bits.Paused)) { return true; } if (m_isCompressed) { - return getAudioCompressed(rbi); + return false; // getAudioCompressed(rbi); } else { - return getAudioUncompressed(rbi); + return getAudioUncompressed(rbi, numOutSamples); } return true; } \ No newline at end of file diff --git a/modules/libSceNgs2/reader.h b/modules/libSceNgs2/reader.h index abccd367..fc73676a 100644 --- a/modules/libSceNgs2/reader.h +++ b/modules/libSceNgs2/reader.h @@ -1,8 +1,6 @@ #pragma once -struct SceNgs2Handle_voice; -struct SceNgs2SamplerVoiceWaveformBlocksParam; -struct SceNgs2RenderBufferInfo; +#include "types.h" class Reader { void* m_pimpl; @@ -11,7 +9,9 @@ class Reader { SceNgs2Handle_voice* voice; - bool getAudioUncompressed(SceNgs2RenderBufferInfo*); + SceNgs2SamplerVoiceState m_state; + + bool getAudioUncompressed(SceNgs2RenderBufferInfo*, uint32_t numOutSamples); bool getAudioCompressed(SceNgs2RenderBufferInfo*); public: @@ -20,5 +20,12 @@ class Reader { bool init(SceNgs2SamplerVoiceWaveformBlocksParam const* param); - bool getAudio(SceNgs2RenderBufferInfo*); + bool getAudio(SceNgs2RenderBufferInfo*, uint32_t numOutSamples); + + void setNewData(void const* start, void const* end); + + void getState(SceNgs2SamplerVoiceState* state) const { + *state = m_state; + state->voiceState = voice->state; + } }; diff --git a/modules/libSceNgs2/types.h b/modules/libSceNgs2/types.h index 5e443a72..dd50b1b7 100644 --- a/modules/libSceNgs2/types.h +++ b/modules/libSceNgs2/types.h @@ -384,6 +384,12 @@ struct SceNgs2SamplerVoiceWaveformBlocksParam { const SceNgs2WaveformBlock* aBlock; }; +struct SceNgs2CustomSamplerVoiceWaveformAddressParam { + SceNgs2VoiceParamHead header; + const void* pDataStart; + const void* pDataEnd; +}; + struct SceNgs2SamplerVoiceSetupParam { SceNgs2VoiceParamHead header; SceNgs2WaveformInfo format; @@ -391,6 +397,20 @@ struct SceNgs2SamplerVoiceSetupParam { uint32_t reserved; }; +struct SceNgs2SamplerVoiceState { + SceNgs2VoiceStateFlags voiceState = {0}; + + float envelopeHeight = 0; + float peakHeight = 0; + uint32_t reserved; + uint64_t numDecodedSamples = 0; + uint64_t decodedDataSize = 0; + uint64_t userData = 0; + const void* waveformData = 0; + + SceNgs2SamplerVoiceState() = default; +}; + struct SceNgs2VoiceCallbackInfo { uintptr_t callbackData; SceNgs2Handle* voiceHandle; From f75fc735d374a3529c2e64f7c422e1e449e427bc Mon Sep 17 00:00:00 2001 From: SysRay Date: Fri, 17 May 2024 20:09:46 +0200 Subject: [PATCH 13/19] ngs2| dump --- modules/libSceNgs2/entry.cpp | 2 +- modules/libSceNgs2/reader.cpp | 27 +++++++++++++-------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/modules/libSceNgs2/entry.cpp b/modules/libSceNgs2/entry.cpp index 3c1c5411..874d2ae1 100644 --- a/modules/libSceNgs2/entry.cpp +++ b/modules/libSceNgs2/entry.cpp @@ -581,7 +581,7 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBu std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); for (auto& voice: system->sampler->voices) { if (voice.second.reader != nullptr) { - // voice.second.reader->getAudio(&rbi[i], numSamples); + //voice.second.reader->getAudio(&rbi[i], numSamples); } } } diff --git a/modules/libSceNgs2/reader.cpp b/modules/libSceNgs2/reader.cpp index 59afe218..010cdb2e 100644 --- a/modules/libSceNgs2/reader.cpp +++ b/modules/libSceNgs2/reader.cpp @@ -243,14 +243,14 @@ bool Reader::getAudioUncompressed(SceNgs2RenderBufferInfo* rbi, uint32_t numOutS return false; } - auto const [formatOut, bytesOut] = convFormatPlanar(rbi->waveType); + auto const [formatOut, bytesOut] = convFormat(rbi->waveType); if (formatOut == AVSampleFormat::AV_SAMPLE_FMT_NONE) return false; - auto const [formatIn, bytesIn] = convFormatPlanar(voice->info.type); + auto const [formatIn, bytesIn] = convFormat(voice->info.type); if (formatIn == AVSampleFormat::AV_SAMPLE_FMT_NONE) return false; - if (swr_alloc_set_opts2(&pimpl->swrCtx, &pimpl->curChannelLayoutOut, formatOut, 48000, &pimpl->curChannelLayoutIn, formatIn, voice->info.sampleRate, 0, - NULL)) { + if (swr_alloc_set_opts2(&pimpl->swrCtx, &pimpl->curChannelLayoutOut, formatOut, voice->info.sampleRate, &pimpl->curChannelLayoutIn, formatIn, + voice->info.sampleRate, 0, NULL)) { LOG_ERR(L"Reader:Couldn't alloc swr"); return false; } @@ -275,30 +275,29 @@ bool Reader::getAudioUncompressed(SceNgs2RenderBufferInfo* rbi, uint32_t numOutS uint32_t const readSize = std::min(rbi->bufferSize, (size_t)pimpl->block.size - pimpl->curOffset); - auto const [formatIn, bytesIn] = convFormatPlanar(voice->info.type); - auto const [formatOut, bytesOut] = convFormatPlanar(rbi->waveType); + auto const [formatIn, bytesIn] = convFormat(voice->info.type); + auto const [formatOut, bytesOut] = convFormat(rbi->waveType); std::vector audioBuffers(((int)rbi->channelsCount)); - auto const channelSizeOut = numOutSamples * bytesOut; + auto const channelSizeOut = (uint32_t)rbi->channelsCount * bytesOut; for (uint8_t n = 0; n < audioBuffers.size(); ++n) { - audioBuffers[n] = &((uint8_t*)rbi->bufferPtr)[n * channelSizeOut]; + audioBuffers[n] = &((uint8_t*)rbi->bufferPtr)[0]; } if (pimpl->block.numSamples > 0) { std::vector audioBuffersIn(((int)voice->info.channelsCount)); + auto const channelSizeIn = (uint32_t)voice->info.channelsCount * bytesOut; for (uint8_t n = 0; n < audioBuffersIn.size(); ++n) { - audioBuffersIn[n] = &((uint8_t*)pimpl->data)[pimpl->curOffset + n * pimpl->block.numSamples]; + audioBuffersIn[n] = &((uint8_t*)pimpl->data)[0]; } - auto numSamples = swr_convert(pimpl->swrCtx, audioBuffers.data(), numOutSamples, audioBuffersIn.data(), pimpl->block.numSamples); + auto numSamples = swr_convert(pimpl->swrCtx, (uint8_t**)&rbi->bufferPtr, numOutSamples, &pimpl->data, pimpl->block.numSamples); + pimpl->block.numSamples = 0; } else { - std::vector audioBuffersIn(((int)voice->info.channelsCount)); - audioBuffersIn[0] = &((uint8_t*)pimpl->data)[pimpl->curOffset]; - - auto numSamples = swr_convert(pimpl->swrCtx, audioBuffers.data(), numOutSamples, nullptr, 0); + auto numSamples = swr_convert(pimpl->swrCtx, (uint8_t**)&rbi->bufferPtr, numOutSamples, nullptr, 0); if (numSamples == 0) { m_state.numDecodedSamples += pimpl->block.numSamples; m_state.decodedDataSize += pimpl->block.size; From 90afd34de20eae4229df1d95a81e4caa161d4e5c Mon Sep 17 00:00:00 2001 From: SysRay Date: Fri, 17 May 2024 20:51:39 +0200 Subject: [PATCH 14/19] +pthread_cancel, call tls destructor != nullptr --- core/kernel/pthread.cpp | 9 +++------ core/runtime/runtimeLinker.cpp | 6 +++--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/core/kernel/pthread.cpp b/core/kernel/pthread.cpp index 1374b5f3..f9e97d28 100644 --- a/core/kernel/pthread.cpp +++ b/core/kernel/pthread.cpp @@ -802,10 +802,8 @@ int cancel(ScePthread_obj obj) { auto thread = getPthread(obj); // todo cancel // int result = ::pthread_cancel(thread->p); - - LOG_USE_MODULE(pthread); - LOG_ERR(L" todo cancel| %S id:%d", thread->name.data(), thread->unique_id); - // LOG_TRACE(L"thread cancel| threadId:%d name:%S result:%d", thread->unique_id, thread->name.c_str(), result); + thread->p.interrupt(); + join(obj, nullptr); return Ok; } @@ -1219,6 +1217,7 @@ void cleanup_thread() { func(arg); thread->cleanupFuncs.pop_back(); } + accessRuntimeLinker().destroyTLSKeys(getSelf()); auto thread_dtors = *getThreadDtors(); @@ -1226,8 +1225,6 @@ void cleanup_thread() { thread_dtors(); } - accessRuntimeLinker().destroyTLSKeys(getSelf()); - accessMemoryManager()->unregisterStack((uint64_t)thread->attr.getStackAddr()); // Delete here if detached, else in join() diff --git a/core/runtime/runtimeLinker.cpp b/core/runtime/runtimeLinker.cpp index f656bfbf..f0850b2e 100644 --- a/core/runtime/runtimeLinker.cpp +++ b/core/runtime/runtimeLinker.cpp @@ -691,13 +691,13 @@ void RuntimeLinker::destroyTLSKeys(uint8_t* obj) { std::unique_lock const lock(m_mutex_int); - m_threadList.erase(pthread::getThreadId(obj)); - for (uint64_t n = m_countcreatePrograms; n < m_dtvKeys.size(); ++n, ++pDtvKey) { if (m_dtvKeys[n].destructor != nullptr) { - m_dtvKeys[n].destructor((void*)pDtvKey[n]); + if (pDtvKey[n] != 0) m_dtvKeys[n].destructor((void*)pDtvKey[n]); } } + + m_threadList.erase(pthread::getThreadId(obj)); } void RuntimeLinker::stopModules() { From 14ccef05892690656f020c3ed0d602096045a837 Mon Sep 17 00:00:00 2001 From: SysRay Date: Fri, 17 May 2024 21:55:32 +0200 Subject: [PATCH 15/19] entry| copy all args --- asm/entry.asm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/asm/entry.asm b/asm/entry.asm index 1cf3226c..89e40a47 100644 --- a/asm/entry.asm +++ b/asm/entry.asm @@ -15,7 +15,9 @@ jmpEntry PROC AND RSP, -10h ; copy entry param to stack - ADD RSP, 24 + ADD RSP, 40 + push [RSI+24] + push [RSI+16] push [RSI+8] push [RSI] ; - From 042da5253988efa6a1fbc7ba78865d395423cbf2 Mon Sep 17 00:00:00 2001 From: SysRay Date: Fri, 17 May 2024 21:56:06 +0200 Subject: [PATCH 16/19] pthread_cancel don't join, --- core/kernel/pthread.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/kernel/pthread.cpp b/core/kernel/pthread.cpp index f9e97d28..48a61ed8 100644 --- a/core/kernel/pthread.cpp +++ b/core/kernel/pthread.cpp @@ -400,11 +400,13 @@ int join(ScePthread_obj obj, void** value) { auto thread = getPthread(obj); thread->p.join(); - LOG_USE_MODULE(pthread); - LOG_DEBUG(L"Delete thread:%d", thread->unique_id); - // Cleanup thread - thread->~PthreadPrivate(); - delete[] obj; + if (!thread->detached) { + LOG_USE_MODULE(pthread); + LOG_DEBUG(L"Delete thread:%d", thread->unique_id); + // Cleanup thread + thread->~PthreadPrivate(); + delete[] obj; + } // - return Ok; } @@ -803,7 +805,6 @@ int cancel(ScePthread_obj obj) { // todo cancel // int result = ::pthread_cancel(thread->p); thread->p.interrupt(); - join(obj, nullptr); return Ok; } From b6664175faabc20f7a0044d6e146bdb2a37a9ba3 Mon Sep 17 00:00:00 2001 From: SysRay Date: Sat, 18 May 2024 15:59:50 +0200 Subject: [PATCH 17/19] _exit| change trace to err --- modules/libkernel/entry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/libkernel/entry.cpp b/modules/libkernel/entry.cpp index 098fc35b..a6bebad2 100644 --- a/modules/libkernel/entry.cpp +++ b/modules/libkernel/entry.cpp @@ -62,7 +62,7 @@ EXPORT SYSV_ABI void __NID(__stack_chk_fail)() { EXPORT SYSV_ABI void __NID(_exit)(int code) { LOG_USE_MODULE(libkernel); - LOG_INFO(L"exit code:%d", code); + LOG_ERR(L"exit code:%d", code); ::exit(code); } From 2f2a4d8d3b426ccb3fd3cd5bbdbbf81b826720d4 Mon Sep 17 00:00:00 2001 From: SysRay Date: Sat, 18 May 2024 16:02:57 +0200 Subject: [PATCH 18/19] format --- modules/libSceNgs2/entry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/libSceNgs2/entry.cpp b/modules/libSceNgs2/entry.cpp index 874d2ae1..3c1c5411 100644 --- a/modules/libSceNgs2/entry.cpp +++ b/modules/libSceNgs2/entry.cpp @@ -581,7 +581,7 @@ EXPORT SYSV_ABI int32_t sceNgs2SystemRender(SceNgs2Handle* sysh, SceNgs2RenderBu std::memset(rbi[i].bufferPtr, 0, rbi[i].bufferSize); for (auto& voice: system->sampler->voices) { if (voice.second.reader != nullptr) { - //voice.second.reader->getAudio(&rbi[i], numSamples); + // voice.second.reader->getAudio(&rbi[i], numSamples); } } } From 35b87ae6259eec2551ccf645f55311427b867a0c Mon Sep 17 00:00:00 2001 From: SysRay Date: Sat, 18 May 2024 16:13:56 +0200 Subject: [PATCH 19/19] fix build, tracelevel --- modules/libSceAudioOut/entry.cpp | 2 +- modules/libSceAvPlayer/avplayer.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/libSceAudioOut/entry.cpp b/modules/libSceAudioOut/entry.cpp index f9c6d3e2..b0bf3b84 100644 --- a/modules/libSceAudioOut/entry.cpp +++ b/modules/libSceAudioOut/entry.cpp @@ -229,7 +229,7 @@ EXPORT SYSV_ABI int32_t sceAudioOutInit(void) { return Err::AudioOut::OUT_OF_MEMORY; } -EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type, int32_t index, uint32_t len, uint32_t freq, uint32_t param) { +EXPORT SYSV_ABI int32_t sceAudioOutOpen(int32_t userId, SceAudioOutPortType type, int32_t index, uint32_t numSamples, uint32_t sampleRate, uint32_t param) { if (!audioInited) return Err::AudioOut::NOT_INIT; LOG_USE_MODULE(libSceAudioOut); LOG_TRACE(L"%S", __FUNCTION__); diff --git a/modules/libSceAvPlayer/avplayer.cpp b/modules/libSceAvPlayer/avplayer.cpp index a5dae8b2..5d93bdb9 100644 --- a/modules/libSceAvPlayer/avplayer.cpp +++ b/modules/libSceAvPlayer/avplayer.cpp @@ -282,9 +282,9 @@ bool Avplayer::getVideoData(void* info, bool isEx) { if (retRecv < 0) { if (retRecv == AVERROR(EAGAIN)) { if (!m_isStop) { - LOG_DEBUG(L"-> wait video frame"); + LOG_TRACE(L"-> wait video frame"); m_video.m_cond.wait(lock); - LOG_DEBUG(L"<- wait video frame"); + LOG_TRACE(L"<- wait video frame"); continue; } } else if (retRecv != AVERROR_EOF) { @@ -315,7 +315,7 @@ bool Avplayer::getVideoData(void* info, bool isEx) { auto const timestamp = (int64_t)(1000.0 * av_q2d(m_video.stream->time_base) * m_video.frame->best_effort_timestamp); // timestamp[seconds] to [ms] auto const curTime = (av_gettime() - m_startTime) / 1000; // [us] to [ms] - LOG_DEBUG(L"video frame timestamp:%lld", curTime); + LOG_TRACE(L"video frame timestamp:%lld", curTime); if (timestamp > curTime) { return false; } @@ -393,9 +393,9 @@ bool Avplayer::getAudioData(SceAvPlayerFrameInfo* info) { if (retRecv < 0) { if (retRecv == AVERROR(EAGAIN)) { if (!m_isStop) { - LOG_DEBUG(L"-> wait audio frame"); + LOG_TRACE(L"-> wait audio frame"); m_audio.m_cond.wait(lock); - LOG_DEBUG(L"<- wait audio frame"); + LOG_TRACE(L"<- wait audio frame"); continue; } } else if (retRecv != AVERROR_EOF) {