From 980e6f90f0243368b60ad2f0211c4f2067f3edab Mon Sep 17 00:00:00 2001 From: Martin Baliet Date: Tue, 7 May 2024 16:07:14 +0200 Subject: [PATCH] ngs2| dump --- modules/libSceNgs2/codes.h | 3 + modules/libSceNgs2/entry.cpp | 191 +++++++++++++++++++++++++------ modules/libSceNgs2/readFuncs.cpp | 20 +++- modules/libSceNgs2/reader.cpp | 184 +++++++++++++++++++---------- modules/libSceNgs2/reader.h | 7 +- modules/libSceNgs2/types.h | 81 +++++++------ modules/libSceNpParty/entry.cpp | 2 +- 7 files changed, 349 insertions(+), 139 deletions(-) diff --git a/modules/libSceNgs2/codes.h b/modules/libSceNgs2/codes.h index 045f490..a0b2dfa 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 f0d789c..ffce1b1 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; + if (voh == nullptr) return getErr(ErrCode::_EINVAL); + 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); + auto curItem = phead; + int32_t ret = Ok; + while (true) { + uint16_t const rackId = curItem->id >> 16; - LOG_ERR(L"Unhandled rackId: %08x", rackId); + 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); - return Ok; + if (curItem->next == 0 || ret != Ok) break; + + curItem = (SceNgs2VoiceParamHead*)((uint64_t)curItem + curItem->next); + } + + 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 b389c9c..a579ec3 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->loopBeginPos = 0; + wf->loopEndPos = totalSize; - wf->samplesCount = astream->nb_frames; - - 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 295aa80..208e1a4 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; - - userData.ptr = data; - userData.size = size; - userData.curOffset = 0; - // Init Setup - auto aBufferIo = (uint8_t*)av_malloc(4096 + AV_INPUT_BUFFER_PADDING_SIZE); + // 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); + // 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); }); + // 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); }); + // // Open the input + // pimpl->fmtctx = avformat_alloc_context(); + // cleanup.emplace_back([&] { avformat_free_context(pimpl->fmtctx); }); - fmtctx->pb = avioctx; - fmtctx->flags |= AVFMT_FLAG_CUSTOM_IO; + // pimpl->fmtctx->pb = avioctx; + // pimpl->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); }); + // 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->stream_idx = av_find_best_stream(fmtctx, AVMEDIA_TYPE_AUDIO, -1, -1, &pimpl->codec, 0); + // pimpl->stream_idx = av_find_best_stream(pimpl->fmtctx, AVMEDIA_TYPE_AUDIO, -1, -1, &pimpl->codec, 0); - if (pimpl->stream_idx < 0) { - LOG_ERR(L"Reader: no audio stream"); - return false; - } + // if (pimpl->stream_idx < 0) { + // LOG_ERR(L"Reader: no audio stream"); + // return false; + // } - pimpl->astream = fmtctx->streams[pimpl->stream_idx]; + // 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) { - LOG_ERR(L"Reader: avcodec_parameters_to_context err:%d", err); - return false; - } - cleanup.emplace_back([&] { avcodec_free_context(&pimpl->codecContext); }); + // 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 - // - + // // 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 7e0dc17..9841636 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 ecbe349..712cc01 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 f6d25b7..cb09c62 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; }