ngs2| dump

This commit is contained in:
Martin Baliet 2024-05-07 16:07:14 +02:00
parent 8f666c12f8
commit 980e6f90f0
7 changed files with 349 additions and 139 deletions

View File

@ -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;

View File

@ -1,8 +1,3 @@
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswresample/swresample.h>
}
#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 <boost/thread.hpp>
#include <set>
LOG_DEFINE_MODULE(libSceNgs2);
namespace {
static boost::mutex MUTEX_INT;
struct Impl {
std::set<SceNgs2Handle*> 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<Reader>().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;
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;

View File

@ -4,10 +4,12 @@
#include "core/kernel/filesystem.h"
#include "logging.h"
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
#include <functional>
#include <list>
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;
}

View File

@ -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;
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;
}

View File

@ -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);
};

View File

@ -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 {
@ -185,13 +196,10 @@ struct SceNgs2RackOption {
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];
};
@ -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)

View File

@ -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;
}