-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
a proper branch for fixing issues of sceMp3 #5828
Changes from 2 commits
b25de88
71e778d
5f6a679
b46f47b
5b5bd83
8a62032
10f78be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,7 +46,7 @@ int __Mp3InitContext(Mp3Context *ctx); | |
struct Mp3Context { | ||
Mp3Context() | ||
#ifdef USE_FFMPEG | ||
: avformat_context(NULL), avio_context(NULL), resampler_context(NULL) { | ||
: avformat_context(NULL), avio_context(NULL), resampler_context(NULL) { | ||
#else | ||
{ | ||
#endif | ||
|
@@ -149,83 +149,70 @@ void __Mp3DoState(PointerWrap &p) { | |
} | ||
|
||
int sceMp3Decode(u32 mp3, u32 outPcmPtr) { | ||
DEBUG_LOG(ME, "sceMp3Decode(%08x,%08x)", mp3, outPcmPtr); | ||
|
||
Mp3Context *ctx = getMp3Ctx(mp3); | ||
if (!ctx) { | ||
ERROR_LOG(ME, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); | ||
return -1; | ||
} | ||
|
||
// Nothing to decode | ||
if (ctx->bufferAvailable == 0 || ctx->readPosition >= ctx->mp3StreamEnd) { | ||
return 0; | ||
} | ||
int bytesdecoded = 0; | ||
int bytespcm = 0; | ||
|
||
#ifndef USE_FFMPEG | ||
Memory::Memset(ctx->mp3PcmBuf, 0, ctx->mp3PcmBufSize); | ||
Memory::Write_U32(ctx->mp3PcmBuf, outPcmPtr); | ||
#else | ||
|
||
AVFrame frame; | ||
memset(&frame, 0, sizeof(frame)); | ||
AVPacket packet; | ||
av_init_packet(&packet); | ||
AVFrame *frame = av_frame_alloc(); | ||
int got_frame = 0, ret; | ||
static int audio_frame_count = 0; | ||
|
||
while (!got_frame) { | ||
if ((ret = av_read_frame(ctx->avformat_context, &packet)) < 0) | ||
break; | ||
AVPacket packet; | ||
av_init_packet(&packet); | ||
|
||
if ((ret = av_read_frame(ctx->avformat_context, &packet)) < 0){ | ||
av_free_packet(&packet); | ||
break; | ||
} | ||
if (packet.stream_index == ctx->audio_stream_index) { | ||
av_frame_unref(&frame); | ||
av_frame_unref(frame); | ||
got_frame = 0; | ||
ret = avcodec_decode_audio4(ctx->decoder_context, &frame, &got_frame, &packet); | ||
ret = avcodec_decode_audio4(ctx->decoder_context, frame, &got_frame, &packet); | ||
if (ret < 0) { | ||
ERROR_LOG(ME, "avcodec_decode_audio4: Error decoding audio %d", ret); | ||
continue; | ||
} | ||
if (got_frame) { | ||
//char buf[1024] = ""; | ||
//av_ts_make_time_string(buf, frame.pts, &ctx->decoder_context->time_base); | ||
//DEBUG_LOG(ME, "audio_frame n:%d nb_samples:%d pts:%s", audio_frame_count++, frame.nb_samples, buf); | ||
|
||
/* | ||
u8 *audio_dst_data; | ||
int audio_dst_linesize; | ||
|
||
ret = av_samples_alloc(&audio_dst_data, &audio_dst_linesize, frame.channels, frame.nb_samples, (AVSampleFormat)frame.format, 1); | ||
if (ret < 0) { | ||
ERROR_LOG(ME, "av_samples_alloc: Could not allocate audio buffer %d", ret); | ||
return -1; | ||
} | ||
*/ | ||
|
||
int decoded = av_samples_get_buffer_size(NULL, frame.channels, frame.nb_samples, (AVSampleFormat)frame.format, 1); | ||
int decoded = av_samples_get_buffer_size(NULL, frame->channels, frame->nb_samples, (AVSampleFormat)frame->format, 1); | ||
|
||
u8* out = Memory::GetPointer(ctx->mp3PcmBuf + bytesdecoded); | ||
ret = swr_convert(ctx->resampler_context, &out, frame.nb_samples, (const u8**)frame.extended_data, frame.nb_samples); | ||
ret = swr_convert(ctx->resampler_context, &out, frame->nb_samples, (const u8**)frame->extended_data, frame->nb_samples); | ||
if (ret < 0) { | ||
ERROR_LOG(ME, "swr_convert: Error while converting %d", ret); | ||
return -1; | ||
av_free_packet(&packet); | ||
break; | ||
} | ||
__AdjustBGMVolume((s16 *)out, frame.nb_samples * frame.channels); | ||
// always convert to stereo pcm | ||
__AdjustBGMVolume((s16 *)out, frame->nb_samples * 2); | ||
|
||
//av_samples_copy(&audio_dst_data, frame.data, 0, 0, frame.nb_samples, frame.channels, (AVSampleFormat)frame.format); | ||
|
||
//memcpy(Memory::GetPointer(ctx->mp3PcmBuf + bytesdecoded), audio_dst_data, decoded); | ||
// the decoded size | ||
bytesdecoded += decoded; | ||
// av_freep(&audio_dst_data[0]); | ||
// the output pcm size | ||
bytespcm += ret * 2 * 2; | ||
// the decoded source data size, always increasing even for looping | ||
ctx->mp3DecodedBytes = packet.pos; | ||
} | ||
} | ||
av_free_packet(&packet); | ||
} // end while | ||
av_frame_free(&frame); | ||
// if no decoded output, we don't need to play | ||
if (bytesdecoded > 0){ | ||
Memory::Write_U32(ctx->mp3PcmBuf, outPcmPtr); | ||
} | ||
Memory::Write_U32(ctx->mp3PcmBuf, outPcmPtr); | ||
#endif | ||
|
||
#if 0 && defined(_DEBUG) | ||
#if 0 && defined(_DEBUG) | ||
char fileName[256]; | ||
sprintf(fileName, "out.wav", mp3); | ||
|
||
|
@@ -240,14 +227,13 @@ int sceMp3Decode(u32 mp3, u32 outPcmPtr) { | |
|
||
fclose(file); | ||
} | ||
#endif | ||
// 2 bytes per channel and we have frame.channels in mp3 source | ||
// learn japanese v0.9 frame.channels = 0 | ||
if (frame.channels == 0) | ||
frame.channels = 2; | ||
ctx->mp3SumDecodedSamples += bytesdecoded / (2 * frame.channels); | ||
#endif | ||
|
||
// 2 bytes per channel and we have ctx->mp3Channels in mp3 source | ||
ctx->mp3SumDecodedSamples += bytesdecoded / (2 * ctx->mp3Channels); | ||
|
||
return bytesdecoded; | ||
DEBUG_LOG(ME, "%08x = sceMp3Decode(%08x,%08x)", bytespcm, mp3, outPcmPtr); | ||
return bytespcm; | ||
} | ||
|
||
int sceMp3ResetPlayPosition(u32 mp3) { | ||
|
@@ -278,45 +264,80 @@ int sceMp3CheckStreamDataNeeded(u32 mp3) { | |
static int readFunc(void *opaque, uint8_t *buf, int buf_size) { | ||
Mp3Context *ctx = static_cast<Mp3Context*>(opaque); | ||
|
||
int res = 0; | ||
while (ctx->bufferAvailable && buf_size) { | ||
// Maximum bytes we can read | ||
int to_read = std::min(ctx->bufferAvailable, buf_size); | ||
|
||
// Don't read past the end if the buffer loops | ||
to_read = std::min(ctx->mp3BufSize - ctx->bufferRead, to_read); | ||
memcpy(buf + res, Memory::GetCharPointer(ctx->mp3Buf + ctx->bufferRead), to_read); | ||
if (!g_Config.bFFmpegCallback){ | ||
// old callback method | ||
int res = 0; | ||
while (ctx->bufferAvailable && buf_size) { | ||
// Maximum bytes we can read | ||
int to_read = std::min(ctx->bufferAvailable, buf_size); | ||
|
||
// Don't read past the end if the buffer loops | ||
to_read = std::min(ctx->mp3BufSize - ctx->bufferRead, to_read); | ||
memcpy(buf + res, Memory::GetCharPointer(ctx->mp3Buf + ctx->bufferRead), to_read); | ||
|
||
ctx->bufferRead += to_read; | ||
if (ctx->bufferRead == ctx->mp3BufSize) | ||
ctx->bufferRead = 0; | ||
ctx->bufferAvailable -= to_read; | ||
buf_size -= to_read; | ||
res += to_read; | ||
} | ||
|
||
ctx->bufferRead += to_read; | ||
if (ctx->bufferRead == ctx->mp3BufSize) | ||
if (ctx->bufferAvailable == 0) { | ||
ctx->bufferRead = 0; | ||
ctx->bufferAvailable -= to_read; | ||
buf_size -= to_read; | ||
res += to_read; | ||
} | ||
|
||
if (ctx->bufferAvailable == 0) { | ||
ctx->bufferRead = 0; | ||
ctx->bufferWrite = 0; | ||
} | ||
|
||
#if 0 && defined(_DEBUG) | ||
char fileName[256]; | ||
sprintf(fileName, "out.mp3"); | ||
|
||
FILE * file = fopen(fileName, "a+b"); | ||
if (file) { | ||
if (!Memory::IsValidAddress(ctx->mp3Buf)) { | ||
ERROR_LOG(ME, "sceMp3Decode mp3Buf %08X is not a valid address!", ctx->mp3Buf); | ||
ctx->bufferWrite = 0; | ||
} | ||
|
||
fwrite(buf, 1, res, file); | ||
|
||
fclose(file); | ||
return res; | ||
} | ||
else{ | ||
// new call back method, for fixing issues as | ||
// 1. control loops and buffer copies. | ||
// 2. Miku custom BGM playing | ||
// 3. lost last voice | ||
int res = 0; | ||
static int pbufpos = 0; | ||
// if we still have available data in mp3Buf | ||
if (ctx->bufferAvailable) { | ||
// Maximum bytes we can read | ||
int to_read = std::min(ctx->bufferAvailable, buf_size - pbufpos); | ||
|
||
// Don't read past the end of mp3Buf if loops | ||
to_read = std::min(ctx->mp3BufSize - ctx->bufferRead, to_read); | ||
|
||
// we will fill the ffmpeg's buffer from the current position | ||
memcpy(buf + pbufpos, Memory::GetCharPointer(ctx->mp3Buf + ctx->bufferRead), to_read); | ||
|
||
ctx->bufferRead += to_read; | ||
// if mp3Buf is full read, we reset the read position to its begining | ||
if (ctx->bufferRead == ctx->mp3BufSize) | ||
ctx->bufferRead = 0; | ||
ctx->bufferAvailable -= to_read; | ||
pbufpos += to_read; | ||
// if ffmpeg buffer is full charged, we reset pointer to its begining | ||
if (pbufpos == buf_size) | ||
pbufpos = 0; | ||
res = to_read; | ||
} // otherwise, we have no data in mp3Buf | ||
else { | ||
ctx->bufferRead = 0; | ||
ctx->bufferWrite = 0; | ||
// if the mp3 file have not been all decoded, we should not stop but continue | ||
// we can control the loops here. If the mp3 file has been fully decoded, then return zero to stop loops, return buf_size to continue loops. | ||
int looped = ctx->mp3DecodedBytes / (ctx->mp3StreamEnd - ctx->mp3StreamStart); // number of time we have looped | ||
if (ctx->mp3LoopNum == -1){ // if loop all the time | ||
return res == 0 ? buf_size : res; // always looping | ||
} | ||
else if (ctx->mp3LoopNum > 0 && ctx->mp3LoopNum - looped < -1){ // if loop more than once | ||
return 0; // stop playing immediately when number of loops reached | ||
} | ||
else if (ctx->mp3LoopNum == 0 && looped == 0){ // only play once and still not stopped | ||
// if res == 0, i.e. we have copied everything from mp3Buff to ffmpeg, but the decoding still not finished (maybe due to latency). | ||
// Thus we can not return 0 to stop playing, we must return buf_size until the decoding is finishes (i.e., looped == 1). | ||
return res == 0 ? buf_size : res; | ||
} | ||
} | ||
return res; | ||
} | ||
#endif | ||
|
||
return res; | ||
} | ||
|
||
u32 sceMp3ReserveMp3Handle(u32 mp3Addr) { | ||
|
@@ -336,10 +357,10 @@ u32 sceMp3ReserveMp3Handle(u32 mp3Addr) { | |
ctx->mp3PcmBufSize = Memory::Read_U32(mp3Addr + 28); | ||
} | ||
ctx->readPosition = ctx->mp3StreamStart; | ||
ctx->mp3MaxSamples = ctx->mp3PcmBufSize / 4 ; | ||
ctx->mp3MaxSamples = ctx->mp3PcmBufSize / 4; | ||
ctx->mp3DecodedBytes = 0; | ||
ctx->mp3SumDecodedSamples = 0; | ||
ctx->mp3LoopNum = -1; | ||
ctx->mp3LoopNum = 0; | ||
ctx->mp3Channels = 2; | ||
ctx->mp3Bitrate = 128; | ||
ctx->mp3SamplingRate = 44100; | ||
|
@@ -404,10 +425,16 @@ int __Mp3InitContext(Mp3Context *ctx) { | |
return -1; | ||
} | ||
|
||
int want_sample_rate = ctx->decoder_context->sample_rate; | ||
if (g_Config.bFixSampleRate){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just wonder if re-sampling to 44100 , it fixes the mono voice but break other games ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opps, I forget to change the comment. this will be misunderstanding. I will change the comment here. I‘ve add a hack menu into UI (see figure above), according to this menu, the user can choose to fix or not the sample rate to 44100. Some of games is improved when fixed, while some not. So in this case, I propose an audio hack menu :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. so basically only affect sound quality . There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I think we might always want to resample to 44100 if that's what happens on the real PSP, which seems to be the case if this fixes things. If so we don't need a hack setting, we simply always pass in 44100 to swr_alloc_set_opts. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've seen a game Miku has a weak quality effact. It's custom bgm is 48000 frame rate mp3, if we fix 44100, the sound is a little bit nonsmooth comapring to 48000. But many others games really have good improvement especially such as mono audios, and lower freq audios. Thus, the effect is not always guaranteed to be good, so I think we could propose this hack for the moment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've also analyze AAC audio passsing by sceAudiocodec, it does not call sceVaudioChReserve, I guess the game maybe do itself? in this case, resampling will reduce half of the output samples, from 0x1000 to 0x800. We will get even worst sound effect. What do you think to fix this situation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I seen a comment in __AudioMix() .Probably all resampleing should be done here instead of sceMp3 or sceAtrac ? // TODO: if mixFrequency != the actual output frequency, resample! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But we have not enough information about stream in this function! we only have buffers and number of frames. we even don't know where is the stream come from? which format? stereo or not? float or int? 8-bit?16-bit? or 32-bit?... So personnally, I don't think it's easy to do resampling here. It's better that the stream here is already standarlized as 44100 stereo s16 frames. So, if the stream is already standarlized, why we still care about the output frequency? Ps:I think it should be the simulator to do the playing job not the game? if the simulator do it, we do not really need care about what frequency the game asked, it's just an information to tell emulator (or psp in real machine) the right freq of the audio source. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The game could do things to the audio stream, though. And it can come from other sources than mp3. If the PSP doesn't do it on mp3s, it shouldn't be done there. And another hack setting here doesn't seem great. I know people will create forks if there aren't enough hacks, but I may create my own fork without the crappy hacks and just change things there if there are too many. The danger goes both ways. -[Unknown] There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've tried a new way in sceAac module which not use callback function of ffmpeg at all, and it works well during my test in Fortix, looping is also all right :) @hrydgard @unknownbrackets please have a look #5836, if this way is better, we can use the same code to sceMp3. |
||
// audio hack to fix resampled pcm sample rate to 44100 (for voice speed issue as "Hanayaka Nari Wa ga Ichizoku") | ||
want_sample_rate = 44100; | ||
} | ||
// always convert to PCM S16LE, 44100Hz, stereo | ||
ctx->resampler_context = swr_alloc_set_opts(NULL, | ||
ctx->decoder_context->channel_layout, | ||
AV_CH_LAYOUT_STEREO, | ||
AV_SAMPLE_FMT_S16, | ||
ctx->decoder_context->sample_rate, | ||
want_sample_rate, | ||
ctx->decoder_context->channel_layout, | ||
ctx->decoder_context->sample_fmt, | ||
ctx->decoder_context->sample_rate, | ||
|
@@ -482,14 +509,13 @@ int sceMp3GetMaxOutputSample(u32 mp3) | |
} | ||
|
||
int sceMp3GetSumDecodedSample(u32 mp3) { | ||
ERROR_LOG_REPORT(ME, "UNIMPL sceMp3GetSumDecodedSample(%08X)", mp3); | ||
|
||
Mp3Context *ctx = getMp3Ctx(mp3); | ||
if (!ctx) { | ||
ERROR_LOG(ME, "%s: bad mp3 handle %08x", __FUNCTION__, mp3); | ||
return -1; | ||
} | ||
|
||
DEBUG_LOG(ME, "%08x = sceMp3GetSumDecodedSample(%08X)", ctx->mp3SumDecodedSamples, mp3); | ||
return ctx->mp3SumDecodedSamples; | ||
} | ||
|
||
|
@@ -584,10 +610,8 @@ int sceMp3NotifyAddStreamData(u32 mp3, int size) { | |
if (ctx->bufferWrite >= ctx->mp3BufSize) | ||
ctx->bufferWrite %= ctx->mp3BufSize; | ||
|
||
if (ctx->readPosition >= ctx->mp3StreamEnd && ctx->mp3LoopNum != 0) { | ||
if (ctx->readPosition >= ctx->mp3StreamEnd) { | ||
ctx->readPosition = ctx->mp3StreamStart; | ||
if (ctx->mp3LoopNum > 0) | ||
ctx->mp3LoopNum--; | ||
} | ||
return 0; | ||
} | ||
|
@@ -656,30 +680,30 @@ u32 sceMp3LowLevelDecode() { | |
} | ||
|
||
const HLEFunction sceMp3[] = { | ||
{0x07EC321A,WrapU_U<sceMp3ReserveMp3Handle>,"sceMp3ReserveMp3Handle"}, | ||
{0x0DB149F4,WrapI_UI<sceMp3NotifyAddStreamData>,"sceMp3NotifyAddStreamData"}, | ||
{0x2A368661,WrapI_U<sceMp3ResetPlayPosition>,"sceMp3ResetPlayPosition"}, | ||
{0x354D27EA,WrapI_U<sceMp3GetSumDecodedSample>,"sceMp3GetSumDecodedSample"}, | ||
{0x35750070,WrapI_V<sceMp3InitResource>,"sceMp3InitResource"}, | ||
{0x3C2FA058,WrapI_V<sceMp3TermResource>,"sceMp3TermResource"}, | ||
{0x3CEF484F,WrapI_UI<sceMp3SetLoopNum>,"sceMp3SetLoopNum"}, | ||
{0x44E07129,WrapI_U<sceMp3Init>,"sceMp3Init"}, | ||
{0x732B042A,WrapU_V<sceMp3EndEntry>,"sceMp3EndEntry"}, | ||
{0x7F696782,WrapI_U<sceMp3GetMp3ChannelNum>,"sceMp3GetMp3ChannelNum"}, | ||
{0x87677E40,WrapI_U<sceMp3GetBitRate>,"sceMp3GetBitRate"}, | ||
{0x87C263D1,WrapI_U<sceMp3GetMaxOutputSample>,"sceMp3GetMaxOutputSample"}, | ||
{0x8AB81558,WrapU_V<sceMp3StartEntry>,"sceMp3StartEntry"}, | ||
{0x8F450998,WrapI_U<sceMp3GetSamplingRate>,"sceMp3GetSamplingRate"}, | ||
{0xA703FE0F,WrapI_UUUU<sceMp3GetInfoToAddStreamData>,"sceMp3GetInfoToAddStreamData"}, | ||
{0xD021C0FB,WrapI_UU<sceMp3Decode>,"sceMp3Decode"}, | ||
{0xD0A56296,WrapI_U<sceMp3CheckStreamDataNeeded>,"sceMp3CheckStreamDataNeeded"}, | ||
{0xD8F54A51,WrapI_U<sceMp3GetLoopNum>,"sceMp3GetLoopNum"}, | ||
{0xF5478233,WrapI_U<sceMp3ReleaseMp3Handle>,"sceMp3ReleaseMp3Handle"}, | ||
{0xAE6D2027,WrapU_U<sceMp3GetMPEGVersion>,"sceMp3GetMPEGVersion"}, | ||
{0x3548AEC8,WrapU_U<sceMp3GetFrameNum>,"sceMp3GetFrameNum"}, | ||
{0x0840e808,WrapU_UI<sceMp3ResetPlayPositionByFrame>,"sceMp3ResetPlayPositionByFrame"}, | ||
{0x1b839b83,WrapU_V<sceMp3LowLevelInit>,"sceMp3LowLevelInit"}, | ||
{0xe3ee2c81,WrapU_V<sceMp3LowLevelDecode>,"sceMp3LowLevelDecode"} | ||
{ 0x07EC321A, WrapU_U<sceMp3ReserveMp3Handle>, "sceMp3ReserveMp3Handle" }, | ||
{ 0x0DB149F4, WrapI_UI<sceMp3NotifyAddStreamData>, "sceMp3NotifyAddStreamData" }, | ||
{ 0x2A368661, WrapI_U<sceMp3ResetPlayPosition>, "sceMp3ResetPlayPosition" }, | ||
{ 0x354D27EA, WrapI_U<sceMp3GetSumDecodedSample>, "sceMp3GetSumDecodedSample" }, | ||
{ 0x35750070, WrapI_V<sceMp3InitResource>, "sceMp3InitResource" }, | ||
{ 0x3C2FA058, WrapI_V<sceMp3TermResource>, "sceMp3TermResource" }, | ||
{ 0x3CEF484F, WrapI_UI<sceMp3SetLoopNum>, "sceMp3SetLoopNum" }, | ||
{ 0x44E07129, WrapI_U<sceMp3Init>, "sceMp3Init" }, | ||
{ 0x732B042A, WrapU_V<sceMp3EndEntry>, "sceMp3EndEntry" }, | ||
{ 0x7F696782, WrapI_U<sceMp3GetMp3ChannelNum>, "sceMp3GetMp3ChannelNum" }, | ||
{ 0x87677E40, WrapI_U<sceMp3GetBitRate>, "sceMp3GetBitRate" }, | ||
{ 0x87C263D1, WrapI_U<sceMp3GetMaxOutputSample>, "sceMp3GetMaxOutputSample" }, | ||
{ 0x8AB81558, WrapU_V<sceMp3StartEntry>, "sceMp3StartEntry" }, | ||
{ 0x8F450998, WrapI_U<sceMp3GetSamplingRate>, "sceMp3GetSamplingRate" }, | ||
{ 0xA703FE0F, WrapI_UUUU<sceMp3GetInfoToAddStreamData>, "sceMp3GetInfoToAddStreamData" }, | ||
{ 0xD021C0FB, WrapI_UU<sceMp3Decode>, "sceMp3Decode" }, | ||
{ 0xD0A56296, WrapI_U<sceMp3CheckStreamDataNeeded>, "sceMp3CheckStreamDataNeeded" }, | ||
{ 0xD8F54A51, WrapI_U<sceMp3GetLoopNum>, "sceMp3GetLoopNum" }, | ||
{ 0xF5478233, WrapI_U<sceMp3ReleaseMp3Handle>, "sceMp3ReleaseMp3Handle" }, | ||
{ 0xAE6D2027, WrapU_U<sceMp3GetMPEGVersion>, "sceMp3GetMPEGVersion" }, | ||
{ 0x3548AEC8, WrapU_U<sceMp3GetFrameNum>, "sceMp3GetFrameNum" }, | ||
{ 0x0840e808, WrapU_UI<sceMp3ResetPlayPositionByFrame>, "sceMp3ResetPlayPositionByFrame" }, | ||
{ 0x1b839b83, WrapU_V<sceMp3LowLevelInit>, "sceMp3LowLevelInit" }, | ||
{ 0xe3ee2c81, WrapU_V<sceMp3LowLevelDecode>, "sceMp3LowLevelDecode" } | ||
}; | ||
|
||
void Register_sceMp3() { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of just blindly multiplying by 2 it would make the code clearer to do this:
and later below
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I will add this