Skip to content

Commit

Permalink
ngs2| dump
Browse files Browse the repository at this point in the history
  • Loading branch information
SysRay committed May 9, 2024
1 parent 5b0ea0b commit 026a889
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 50 deletions.
4 changes: 3 additions & 1 deletion modules/libSceNgs2/entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand All @@ -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]);
}
}
}
Expand Down
42 changes: 42 additions & 0 deletions modules/libSceNgs2/readFuncs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,46 @@ int32_t parseRiffWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* user
wf->numBlocks = 1;

return Ok;
}

std::optional<AVChannelLayout> 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;
}
8 changes: 7 additions & 1 deletion modules/libSceNgs2/readFuncs.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once
#include "types.h"

#include <optional>

using funcReadBuf_t = int (*)(void*, uint8_t*, int);
using funcSeekBuf_t = int64_t (*)(void*, int64_t, int);

Expand All @@ -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);
int32_t parseRiffWave(funcReadBuf_t readFunc, funcSeekBuf_t seekFunc, void* userData, SceNgs2WaveformFormat* wf);

std::optional<struct AVChannelLayout> convChannelLayout(SceNgs2ChannelsCount);

uint32_t getSampleBytes(SceNgs2WaveFormType);
119 changes: 81 additions & 38 deletions modules/libSceNgs2/reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::function<void(void)>> cleanup;

Expand All @@ -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<PImpl>().release();
}

Expand All @@ -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<PImpl>().release();
return true;
}
m_isInit = false;

pimpl->data = (uint8_t const*)param->data;
pimpl->block = param->aBlock[0];
Expand Down Expand Up @@ -100,21 +123,21 @@ 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) {
LOG_ERR(L"avformat_find_stream_info result:%d", res);
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) {
Expand All @@ -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
Expand All @@ -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;
}
// -

Expand All @@ -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;
}
Expand All @@ -234,30 +270,37 @@ 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");
}

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;
}
13 changes: 7 additions & 6 deletions modules/libSceNgs2/reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
};
bool getAudio(SceNgs2RenderBufferInfo*);
};
Loading

0 comments on commit 026a889

Please sign in to comment.