2013-05-06 13:09:40 +00:00
// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
# include <map>
2013-09-17 04:48:14 +00:00
# include <algorithm>
2013-10-27 02:20:44 +00:00
# include "Core/Config.h"
2013-05-20 00:54:14 +00:00
# include "Core/HLE/HLE.h"
2014-03-15 18:22:19 +00:00
# include "Core/HLE/FunctionWrappers.h"
2013-06-22 16:08:43 +00:00
# include "Core/HLE/sceMp3.h"
2013-05-20 00:54:14 +00:00
# include "Core/HW/MediaEngine.h"
2014-03-15 18:22:19 +00:00
# include "Core/MemMap.h"
2013-05-20 00:54:14 +00:00
# include "Core/Reporting.h"
2014-04-11 13:09:31 +00:00
# include "Core/HW/SimpleAudioDec.h"
2013-05-06 13:09:40 +00:00
2014-04-12 00:12:25 +00:00
struct Mp3Context {
public :
int mp3StreamStart ;
int mp3StreamEnd ;
u32 mp3Buf ;
int mp3BufSize ;
u32 mp3PcmBuf ;
int mp3PcmBufSize ;
int readPosition ;
int bufferRead ;
int bufferWrite ;
int bufferAvailable ;
int mp3DecodedBytes ;
int mp3LoopNum ;
int mp3MaxSamples ;
int mp3SumDecodedSamples ;
int mp3Channels ;
int mp3Bitrate ;
int mp3SamplingRate ;
int mp3Version ;
void DoState ( PointerWrap & p ) {
auto s = p . Section ( " Mp3Context " , 1 ) ;
if ( ! s )
return ;
p . Do ( mp3StreamStart ) ;
p . Do ( mp3StreamEnd ) ;
p . Do ( mp3Buf ) ;
p . Do ( mp3BufSize ) ;
p . Do ( mp3PcmBuf ) ;
p . Do ( mp3PcmBufSize ) ;
p . Do ( readPosition ) ;
p . Do ( bufferRead ) ;
p . Do ( bufferWrite ) ;
p . Do ( bufferAvailable ) ;
p . Do ( mp3DecodedBytes ) ;
p . Do ( mp3LoopNum ) ;
p . Do ( mp3MaxSamples ) ;
p . Do ( mp3SumDecodedSamples ) ;
p . Do ( mp3Channels ) ;
p . Do ( mp3Bitrate ) ;
p . Do ( mp3SamplingRate ) ;
p . Do ( mp3Version ) ;
} ;
} ;
static std : : map < u32 , Mp3Context * > mp3Map_old ;
2014-04-11 13:09:31 +00:00
static std : : map < u32 , AuCtx * > mp3Map ;
2014-04-15 07:11:44 +00:00
static const int mp3DecodeDelay = 4000 ;
2014-04-12 00:12:25 +00:00
2014-12-08 09:40:08 +00:00
static AuCtx * getMp3Ctx ( u32 mp3 ) {
2013-05-06 13:09:40 +00:00
if ( mp3Map . find ( mp3 ) = = mp3Map . end ( ) )
return NULL ;
return mp3Map [ mp3 ] ;
}
2013-10-25 03:07:07 +00:00
void __Mp3Shutdown ( ) {
for ( auto it = mp3Map . begin ( ) , end = mp3Map . end ( ) ; it ! = end ; + + it ) {
delete it - > second ;
}
mp3Map . clear ( ) ;
}
void __Mp3DoState ( PointerWrap & p ) {
2014-04-12 00:12:25 +00:00
auto s = p . Section ( " sceMp3 " , 0 , 2 ) ;
2013-10-25 03:07:07 +00:00
if ( ! s )
return ;
2014-04-12 00:12:25 +00:00
if ( s > = 2 ) {
p . Do ( mp3Map ) ;
}
if ( s < = 1 & & p . mode = = p . MODE_READ ) {
p . Do ( mp3Map_old ) ; // read old map
for ( auto it = mp3Map_old . begin ( ) , end = mp3Map_old . end ( ) ; it ! = end ; + + it ) {
auto mp3 = new AuCtx ;
u32 id = it - > first ;
auto mp3_old = it - > second ;
mp3 - > AuBuf = mp3_old - > mp3Buf ;
mp3 - > AuBufSize = mp3_old - > mp3BufSize ;
mp3 - > PCMBuf = mp3_old - > mp3PcmBuf ;
mp3 - > PCMBufSize = mp3_old - > mp3PcmBufSize ;
mp3 - > BitRate = mp3_old - > mp3Bitrate ;
mp3 - > Channels = mp3_old - > mp3Channels ;
mp3 - > endPos = mp3_old - > mp3StreamEnd ;
mp3 - > startPos = mp3_old - > mp3StreamStart ;
mp3 - > LoopNum = mp3_old - > mp3LoopNum ;
mp3 - > SamplingRate = mp3_old - > mp3SamplingRate ;
mp3 - > freq = mp3 - > SamplingRate ;
mp3 - > SumDecodedSamples = mp3_old - > mp3SumDecodedSamples ;
mp3 - > Version = mp3_old - > mp3Version ;
mp3 - > MaxOutputSample = mp3_old - > mp3MaxSamples ;
mp3 - > readPos = mp3_old - > readPosition ;
mp3 - > AuBufAvailable = 0 ; // reset to read from file
2014-04-12 21:16:38 +00:00
mp3 - > askedReadSize = 0 ;
mp3 - > realReadSize = 0 ;
2014-04-12 00:12:25 +00:00
mp3 - > audioType = PSP_CODEC_MP3 ;
mp3 - > decoder = new SimpleAudio ( mp3 - > audioType ) ;
mp3Map [ id ] = mp3 ;
}
}
2013-10-25 03:07:07 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceMp3Decode ( u32 mp3 , u32 outPcmPtr ) {
2013-09-07 20:02:55 +00:00
DEBUG_LOG ( ME , " sceMp3Decode(%08x,%08x) " , mp3 , outPcmPtr ) ;
2013-05-06 13:09:40 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2014-04-15 07:11:44 +00:00
int pcmBytes = ctx - > AuDecode ( outPcmPtr ) ;
if ( ! pcmBytes ) {
// decode data successfully, delay thread
hleDelayResult ( pcmBytes , " mp3 decode " , mp3DecodeDelay ) ;
}
return pcmBytes ;
2013-05-06 13:09:40 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceMp3ResetPlayPosition ( u32 mp3 ) {
2013-09-07 20:02:55 +00:00
DEBUG_LOG ( ME , " SceMp3ResetPlayPosition(%08x) " , mp3 ) ;
2013-05-06 13:09:40 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2014-04-12 00:12:25 +00:00
return ctx - > AuResetPlayPosition ( ) ;
2013-05-06 13:09:40 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceMp3CheckStreamDataNeeded ( u32 mp3 ) {
2013-09-07 20:02:55 +00:00
DEBUG_LOG ( ME , " sceMp3CheckStreamDataNeeded(%08x) " , mp3 ) ;
2013-05-06 13:09:40 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2014-04-12 00:12:25 +00:00
return ctx - > AuCheckStreamDataNeeded ( ) ;
2013-01-20 13:30:16 +00:00
}
2014-12-08 09:40:08 +00:00
static u32 sceMp3ReserveMp3Handle ( u32 mp3Addr ) {
2014-04-13 19:11:04 +00:00
INFO_LOG ( ME , " sceMp3ReserveMp3Handle(%08x) " , mp3Addr ) ;
2014-04-11 13:09:31 +00:00
if ( ! Memory : : IsValidAddress ( mp3Addr ) ) {
2014-04-13 19:11:04 +00:00
ERROR_LOG ( ME , " sceMp3ReserveMp3Handle(%08x) invalid address %08x " , mp3Addr , mp3Addr ) ;
2014-04-11 13:09:31 +00:00
return - 1 ;
2013-01-20 13:30:16 +00:00
}
2014-04-13 19:11:04 +00:00
AuCtx * Au = new AuCtx ;
2014-04-11 13:09:31 +00:00
Au - > startPos = Memory : : Read_U64 ( mp3Addr ) ; // Audio stream start position.
Au - > endPos = Memory : : Read_U32 ( mp3Addr + 8 ) ; // Audio stream end position.
Au - > AuBuf = Memory : : Read_U32 ( mp3Addr + 16 ) ; // Input Au data buffer.
Au - > AuBufSize = Memory : : Read_U32 ( mp3Addr + 20 ) ; // Input Au data buffer size.
Au - > PCMBuf = Memory : : Read_U32 ( mp3Addr + 24 ) ; // Output PCM data buffer.
Au - > PCMBufSize = Memory : : Read_U32 ( mp3Addr + 28 ) ; // Output PCM data buffer size.
2013-01-20 13:30:16 +00:00
2014-05-21 14:59:58 +00:00
DEBUG_LOG ( ME , " startPos %llx endPos %llx mp3buf %08x mp3bufSize %08x PCMbuf %08x PCMbufSize %08x " ,
2014-04-11 13:09:31 +00:00
Au - > startPos , Au - > endPos , Au - > AuBuf , Au - > AuBufSize , Au - > PCMBuf , Au - > PCMBufSize ) ;
2013-01-20 13:30:16 +00:00
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
Au - > audioType = PSP_CODEC_MP3 ;
2014-04-11 13:09:31 +00:00
Au - > Channels = 2 ;
Au - > SumDecodedSamples = 0 ;
Au - > MaxOutputSample = Au - > PCMBufSize / 4 ;
Au - > LoopNum = - 1 ;
Au - > AuBufAvailable = 0 ;
Au - > readPos = Au - > startPos ;
2013-05-06 13:09:40 +00:00
2014-04-11 13:09:31 +00:00
// create Au decoder
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
Au - > decoder = new SimpleAudio ( Au - > audioType ) ;
2013-05-06 13:09:40 +00:00
2014-04-11 13:09:31 +00:00
// close the audio if mp3Addr already exist.
2014-03-30 22:08:38 +00:00
if ( mp3Map . find ( mp3Addr ) ! = mp3Map . end ( ) ) {
delete mp3Map [ mp3Addr ] ;
2014-04-11 13:09:31 +00:00
mp3Map . erase ( mp3Addr ) ;
2014-03-30 22:08:38 +00:00
}
2014-04-11 13:09:31 +00:00
mp3Map [ mp3Addr ] = Au ;
2013-05-06 13:09:40 +00:00
return mp3Addr ;
}
2014-12-08 09:40:08 +00:00
static int sceMp3InitResource ( ) {
2013-09-07 20:02:55 +00:00
WARN_LOG ( ME , " UNIMPL: sceMp3InitResource " ) ;
2013-05-06 13:09:40 +00:00
// Do nothing here
return 0 ;
}
2014-12-08 09:40:08 +00:00
static int sceMp3TermResource ( ) {
2013-09-07 20:02:55 +00:00
WARN_LOG ( ME , " UNIMPL: sceMp3TermResource " ) ;
2013-05-06 13:09:40 +00:00
// Do nothing here
return 0 ;
}
2014-12-08 09:40:08 +00:00
static int __CalculateMp3Channels ( int bitval ) {
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
if ( bitval = = 0 | | bitval = = 1 | | bitval = = 2 ) { // Stereo / Joint Stereo / Dual Channel.
return 2 ;
}
else if ( bitval = = 3 ) { // Mono.
return 1 ;
}
else {
return - 1 ;
}
}
2014-12-08 09:40:08 +00:00
static int __CalculateMp3SampleRates ( int bitval , int mp3version ) {
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
if ( mp3version = = 3 ) { // MPEG Version 1
int valuemapping [ ] = { 44100 , 48000 , 32000 , - 1 } ;
return valuemapping [ bitval ] ;
}
else if ( mp3version = = 2 ) { // MPEG Version 2
int valuemapping [ ] = { 22050 , 24000 , 16000 , - 1 } ;
return valuemapping [ bitval ] ;
}
else if ( mp3version = = 0 ) { // MPEG Version 2.5
int valuemapping [ ] = { 11025 , 12000 , 8000 , - 1 } ;
return valuemapping [ bitval ] ;
}
else {
return - 1 ;
}
}
2014-12-08 09:40:08 +00:00
static int __CalculateMp3Bitrates ( int bitval , int mp3version , int mp3layer ) {
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
if ( mp3version = = 3 ) { // MPEG Version 1
if ( mp3layer = = 3 ) { // Layer I
int valuemapping [ ] = { 0 , 32 , 64 , 96 , 128 , 160 , 192 , 224 , 256 , 288 , 320 , 352 , 384 , 416 , 448 , - 1 } ;
return valuemapping [ bitval ] ;
}
else if ( mp3layer = = 2 ) { // Layer II
int valuemapping [ ] = { 0 , 32 , 48 , 56 , 64 , 80 , 96 , 112 , 128 , 160 , 192 , 224 , 256 , 320 , 384 , - 1 } ;
return valuemapping [ bitval ] ;
}
else if ( mp3layer = = 1 ) { // Layer III
int valuemapping [ ] = { 0 , 32 , 40 , 48 , 56 , 64 , 80 , 96 , 112 , 128 , 160 , 192 , 224 , 256 , 320 , - 1 } ;
return valuemapping [ bitval ] ;
}
else {
return - 1 ;
}
}
else if ( mp3version = = 2 | | mp3version = = 0 ) { // MPEG Version 2 or 2.5
if ( mp3layer = = 3 ) { // Layer I
int valuemapping [ ] = { 0 , 32 , 48 , 56 , 64 , 80 , 96 , 112 , 128 , 144 , 160 , 176 , 192 , 224 , 256 , - 1 } ;
return valuemapping [ bitval ] ;
}
else if ( mp3layer = = 1 | | mp3layer = = 2 ) { // Layer II or III
int valuemapping [ ] = { 0 , 8 , 16 , 24 , 32 , 40 , 48 , 56 , 64 , 80 , 96 , 112 , 128 , 144 , 160 , - 1 } ;
return valuemapping [ bitval ] ;
}
else {
return - 1 ;
}
}
else {
return - 1 ;
}
}
2014-12-08 09:40:08 +00:00
static int __ParseMp3Header ( AuCtx * ctx , bool * isID3 ) {
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
int header = bswap32 ( Memory : : Read_U32 ( ctx - > AuBuf ) ) ;
// ID3 tag , can be seen in Hanayaka Nari Wa ga Ichizoku.
static const int ID3 = 0x49443300 ;
if ( ( header & 0xFFFFFF00 ) = = ID3 ) {
* isID3 = true ;
int size = bswap32 ( Memory : : Read_U32 ( ctx - > AuBuf + ctx - > startPos + 6 ) ) ;
// Highest bit of each byte has to be ignored (format: 0x7F7F7F7F)
size = ( size & 0x7F ) | ( ( size & 0x7F00 ) > > 1 ) | ( ( size & 0x7F0000 ) > > 2 ) | ( ( size & 0x7F000000 ) > > 3 ) ;
header = bswap32 ( Memory : : Read_U32 ( ctx - > AuBuf + ctx - > startPos + 10 + size ) ) ;
}
return header ;
}
2014-12-08 09:40:08 +00:00
static int sceMp3Init ( u32 mp3 ) {
2014-04-13 19:42:46 +00:00
INFO_LOG ( ME , " sceMp3Init(%08x) " , mp3 ) ;
2013-10-25 03:07:07 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-10-25 03:07:07 +00:00
if ( ! ctx ) {
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
return - 1 ;
}
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
// Parse the Mp3 header
2014-06-22 12:01:23 +00:00
bool hasID3Tag = false ;
int header = __ParseMp3Header ( ctx , & hasID3Tag ) ;
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
int layer = ( header > > 17 ) & 0x3 ;
ctx - > Version = ( ( header > > 19 ) & 0x3 ) ;
ctx - > SamplingRate = __CalculateMp3SampleRates ( ( header > > 10 ) & 0x3 , ctx - > Version ) ;
ctx - > Channels = __CalculateMp3Channels ( ( header > > 6 ) & 0x3 ) ;
ctx - > BitRate = __CalculateMp3Bitrates ( ( header > > 12 ) & 0xF , ctx - > Version , layer ) ;
ctx - > freq = ctx - > SamplingRate ;
INFO_LOG ( ME , " sceMp3Init(): channels=%i, samplerate=%iHz, bitrate=%ikbps " , ctx - > Channels , ctx - > SamplingRate , ctx - > BitRate ) ;
// for mp3, if required freq is 48000, reset resampling Frequency to 48000 seems get better sound quality (e.g. Miku Custom BGM)
2014-06-22 12:01:23 +00:00
if ( ctx - > freq = = 48000 ) {
2014-06-22 15:02:04 +00:00
ctx - > decoder - > SetResampleFrequency ( ctx - > freq ) ;
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
}
2014-04-12 21:16:38 +00:00
// For mp3 file, if ID3 tag is detected, we must move startPos to 0x400 (stream start position), remove 0x400 bytes of the sourcebuff, and reduce the available buffer size by 0x400
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
// this is very important for ID3 tag mp3, since our universal audio decoder is for decoding stream part only.
2014-06-22 12:01:23 +00:00
if ( hasID3Tag ) {
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
// if get ID3 tage, we will decode from 0x400
ctx - > startPos = 0x400 ;
2014-06-22 12:01:23 +00:00
ctx - > EatSourceBuff ( 0x400 ) ;
} else {
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
// if no ID3 tag, we will decode from the begining of the file
ctx - > startPos = 0 ;
2014-04-11 13:09:31 +00:00
}
2013-05-12 18:13:07 +00:00
2013-05-06 13:09:40 +00:00
return 0 ;
}
2014-12-08 09:40:08 +00:00
static int sceMp3GetLoopNum ( u32 mp3 ) {
2013-09-07 20:02:55 +00:00
DEBUG_LOG ( ME , " sceMp3GetLoopNum(%08x) " , mp3 ) ;
2014-04-12 21:16:38 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2014-04-12 00:12:25 +00:00
return ctx - > AuGetLoopNum ( ) ;
2013-05-06 13:09:40 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceMp3GetMaxOutputSample ( u32 mp3 ) {
2013-09-07 20:02:55 +00:00
DEBUG_LOG ( ME , " sceMp3GetMaxOutputSample(%08x) " , mp3 ) ;
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2014-04-12 00:12:25 +00:00
return ctx - > AuGetMaxOutputSample ( ) ;
2013-05-06 13:09:40 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceMp3GetSumDecodedSample ( u32 mp3 ) {
2014-04-13 19:42:46 +00:00
INFO_LOG ( ME , " sceMp3GetSumDecodedSample(%08X) " , mp3 ) ;
2013-09-25 03:50:38 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-09-25 03:50:38 +00:00
if ( ! ctx ) {
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
return - 1 ;
}
2014-04-12 00:12:25 +00:00
return ctx - > AuGetSumDecodedSample ( ) ;
2013-05-06 13:09:40 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceMp3SetLoopNum ( u32 mp3 , int loop ) {
2013-09-07 20:02:55 +00:00
INFO_LOG ( ME , " sceMp3SetLoopNum(%08X, %i) " , mp3 , loop ) ;
2013-05-06 13:09:40 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2014-04-12 00:12:25 +00:00
return ctx - > AuSetLoopNum ( loop ) ;
2013-05-06 13:09:40 +00:00
}
2014-06-22 12:01:23 +00:00
2014-12-08 09:40:08 +00:00
static int sceMp3GetMp3ChannelNum ( u32 mp3 ) {
2014-04-12 21:16:38 +00:00
INFO_LOG ( ME , " sceMp3GetMp3ChannelNum(%08X) " , mp3 ) ;
2013-05-06 13:09:40 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2014-04-12 00:12:25 +00:00
return ctx - > AuGetChannelNum ( ) ;
2013-05-06 13:09:40 +00:00
}
2014-06-22 12:01:23 +00:00
2014-12-08 09:40:08 +00:00
static int sceMp3GetBitRate ( u32 mp3 ) {
2014-04-12 21:16:38 +00:00
INFO_LOG ( ME , " sceMp3GetBitRate(%08X) " , mp3 ) ;
2013-05-06 13:09:40 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2014-04-12 00:12:25 +00:00
return ctx - > AuGetBitRate ( ) ;
2013-05-06 13:09:40 +00:00
}
2014-06-22 12:01:23 +00:00
2014-12-08 09:40:08 +00:00
static int sceMp3GetSamplingRate ( u32 mp3 ) {
2014-04-12 21:16:38 +00:00
INFO_LOG ( ME , " sceMp3GetSamplingRate(%08X) " , mp3 ) ;
2013-05-06 13:09:40 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2014-04-12 00:12:25 +00:00
return ctx - > AuGetSamplingRate ( ) ;
2013-05-06 13:09:40 +00:00
}
2013-05-12 20:29:43 +00:00
2014-12-08 09:40:08 +00:00
static int sceMp3GetInfoToAddStreamData ( u32 mp3 , u32 dstPtr , u32 towritePtr , u32 srcposPtr ) {
2014-04-13 19:42:46 +00:00
DEBUG_LOG ( ME , " sceMp3GetInfoToAddStreamData(%08X, %08X, %08X, %08X) " , mp3 , dstPtr , towritePtr , srcposPtr ) ;
2013-01-20 13:30:16 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2014-04-12 00:12:25 +00:00
return ctx - > AuGetInfoToAddStreamData ( dstPtr , towritePtr , srcposPtr ) ;
2013-05-06 13:09:40 +00:00
}
2013-05-12 20:29:43 +00:00
2014-12-08 09:40:08 +00:00
static int sceMp3NotifyAddStreamData ( u32 mp3 , int size ) {
2014-04-13 19:42:46 +00:00
DEBUG_LOG ( ME , " sceMp3NotifyAddStreamData(%08X, %i) " , mp3 , size ) ;
2013-05-12 20:29:43 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-12 20:29:43 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-12 20:29:43 +00:00
return - 1 ;
}
2014-04-12 00:12:25 +00:00
return ctx - > AuNotifyAddStreamData ( size ) ;
2013-05-12 20:29:43 +00:00
}
2014-12-08 09:40:08 +00:00
static int sceMp3ReleaseMp3Handle ( u32 mp3 ) {
2014-04-12 21:16:38 +00:00
INFO_LOG ( ME , " sceMp3ReleaseMp3Handle(%08X) " , mp3 ) ;
2013-05-06 13:09:40 +00:00
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2013-05-06 13:09:40 +00:00
delete ctx ;
2014-04-11 13:09:31 +00:00
mp3Map . erase ( mp3 ) ;
2013-01-20 13:30:16 +00:00
2013-05-06 13:09:40 +00:00
return 0 ;
}
2014-12-08 09:40:08 +00:00
static u32 sceMp3EndEntry ( ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG_REPORT ( ME , " UNIMPL sceMp3EndEntry(...) " ) ;
2013-05-06 13:09:40 +00:00
return 0 ;
}
2014-12-08 09:40:08 +00:00
static u32 sceMp3StartEntry ( ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG_REPORT ( ME , " UNIMPL sceMp3StartEntry(...) " ) ;
2013-05-06 13:09:40 +00:00
return 0 ;
}
2014-12-08 09:40:08 +00:00
static u32 sceMp3GetFrameNum ( u32 mp3 ) {
2014-04-14 09:47:28 +00:00
INFO_LOG ( ME , " sceMp3GetFrameNum(%08x) " , mp3 ) ;
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
if ( ! ctx ) {
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
return - 1 ;
}
return ctx - > AuGetFrameNum ( ) ;
2013-05-06 13:09:40 +00:00
}
2014-12-08 09:40:08 +00:00
static u32 sceMp3GetMPEGVersion ( u32 mp3 ) {
Universal Audio Class
Based on my implementation in sceAac https://github.com/hrydgard/ppsspp/pull/5836
I've created a class AuCtx included in My SimpleAudioDec.cpp/.h which aims at providing a standard easy implementation to support all codecs in ffmpeg.
Here, I also completely re-code sceMp3 file with this class to give an example how to use this class, and it has solved all mp3 issues I've observed in the current master.
Tests on different freq and channels mp3 audios as:
Miku custom BGM (48kHz, stereo), Hanayaka Nari Wa ga Ichizoku(32kHz, mono, a little fast but better than before now), downstreet panic (44.1kHz, stereo), and learn jp09(44.1kHz, stero) are just all right.
Especially, I am very glad to see that Miku's Custom BGMs have no repetition issues in first tone any more and no longer stopped in the first second neither. :)
We will come into a new age to fast support new audio formats from now on I hope :P
2014-04-11 20:56:59 +00:00
INFO_LOG ( ME , " sceMp3GetMPEGVersion(%08x) " , mp3 ) ;
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-05-06 13:09:40 +00:00
if ( ! ctx ) {
2013-09-07 20:02:55 +00:00
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
2013-05-06 13:09:40 +00:00
return - 1 ;
}
2013-01-20 13:30:16 +00:00
2014-04-12 00:12:25 +00:00
return ctx - > AuGetVersion ( ) ;
2013-05-06 13:09:40 +00:00
}
2014-12-08 09:40:08 +00:00
static u32 sceMp3ResetPlayPositionByFrame ( u32 mp3 , int position ) {
2013-12-03 07:36:55 +00:00
DEBUG_LOG ( ME , " sceMp3ResetPlayPositionByFrame(%08x, %i) " , mp3 , position ) ;
2014-04-11 13:09:31 +00:00
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
2013-09-26 09:06:08 +00:00
if ( ! ctx ) {
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
return - 1 ;
}
2014-04-12 00:12:25 +00:00
return ctx - > AuResetPlayPositionByFrame ( position ) ;
2013-09-26 09:06:08 +00:00
}
2014-12-08 09:40:08 +00:00
static u32 sceMp3LowLevelInit ( u32 mp3 ) {
2014-04-14 10:00:19 +00:00
INFO_LOG ( ME , " sceMp3LowLevelInit(%i) " , mp3 ) ;
2014-04-13 19:11:04 +00:00
auto ctx = new AuCtx ;
ctx - > audioType = PSP_CODEC_MP3 ;
2014-04-13 19:15:41 +00:00
// create mp3 decoder
2014-04-13 19:11:04 +00:00
ctx - > decoder = new SimpleAudio ( ctx - > audioType ) ;
2014-04-13 19:42:46 +00:00
// close the audio if mp3 already exists.
2014-04-13 19:11:04 +00:00
if ( mp3Map . find ( mp3 ) ! = mp3Map . end ( ) ) {
delete mp3Map [ mp3 ] ;
mp3Map . erase ( mp3 ) ;
}
mp3Map [ mp3 ] = ctx ;
2013-09-26 09:09:32 +00:00
return 0 ;
}
2014-12-08 09:40:08 +00:00
static u32 sceMp3LowLevelDecode ( u32 mp3 , u32 sourceAddr , u32 sourceBytesConsumedAddr , u32 samplesAddr , u32 sampleBytesAddr ) {
2014-04-13 19:11:04 +00:00
// sourceAddr: input mp3 stream buffer
// sourceBytesConsumedAddr: consumed bytes decoded in source
// samplesAddr: output pcm buffer
// sampleBytesAddr: output pcm size
DEBUG_LOG ( ME , " sceMp3LowLevelDecode(%08x, %08x, %08x, %08x, %08x) " , mp3 , sourceAddr , sourceBytesConsumedAddr , samplesAddr , sampleBytesAddr ) ;
AuCtx * ctx = getMp3Ctx ( mp3 ) ;
if ( ! ctx ) {
ERROR_LOG ( ME , " %s: bad mp3 handle %08x " , __FUNCTION__ , mp3 ) ;
return - 1 ;
}
if ( ! Memory : : IsValidAddress ( sourceAddr ) | | ! Memory : : IsValidAddress ( sourceBytesConsumedAddr ) | |
2014-06-22 12:01:23 +00:00
! Memory : : IsValidAddress ( samplesAddr ) | | ! Memory : : IsValidAddress ( sampleBytesAddr ) ) {
2014-04-13 19:11:04 +00:00
ERROR_LOG ( ME , " sceMp3LowLevelDecode(%08x, %08x, %08x, %08x, %08x) : invalid address in args " , mp3 , sourceAddr , sourceBytesConsumedAddr , samplesAddr , sampleBytesAddr ) ;
return - 1 ;
}
auto inbuff = Memory : : GetPointer ( sourceAddr ) ;
auto outbuff = Memory : : GetPointer ( samplesAddr ) ;
int outpcmbytes = 0 ;
2014-06-22 12:01:23 +00:00
ctx - > decoder - > Decode ( ( void * ) inbuff , 4096 , outbuff , & outpcmbytes ) ;
2014-04-13 19:11:04 +00:00
2014-06-22 15:02:04 +00:00
Memory : : Write_U32 ( ctx - > decoder - > GetSourcePos ( ) , sourceBytesConsumedAddr ) ;
2014-04-13 19:11:04 +00:00
Memory : : Write_U32 ( outpcmbytes , sampleBytesAddr ) ;
2013-09-26 09:09:32 +00:00
return 0 ;
}
2013-01-20 13:30:16 +00:00
const HLEFunction sceMp3 [ ] = {
2015-03-22 23:57:56 +00:00
{ 0X07EC321A , & WrapU_U < sceMp3ReserveMp3Handle > , " sceMp3ReserveMp3Handle " , ' x ' , " x " } ,
{ 0X0DB149F4 , & WrapI_UI < sceMp3NotifyAddStreamData > , " sceMp3NotifyAddStreamData " , ' i ' , " xi " } ,
{ 0X2A368661 , & WrapI_U < sceMp3ResetPlayPosition > , " sceMp3ResetPlayPosition " , ' i ' , " x " } ,
{ 0X354D27EA , & WrapI_U < sceMp3GetSumDecodedSample > , " sceMp3GetSumDecodedSample " , ' i ' , " x " } ,
{ 0X35750070 , & WrapI_V < sceMp3InitResource > , " sceMp3InitResource " , ' i ' , " " } ,
{ 0X3C2FA058 , & WrapI_V < sceMp3TermResource > , " sceMp3TermResource " , ' i ' , " " } ,
{ 0X3CEF484F , & WrapI_UI < sceMp3SetLoopNum > , " sceMp3SetLoopNum " , ' i ' , " xi " } ,
{ 0X44E07129 , & WrapI_U < sceMp3Init > , " sceMp3Init " , ' i ' , " x " } ,
{ 0X732B042A , & WrapU_V < sceMp3EndEntry > , " sceMp3EndEntry " , ' x ' , " " } ,
{ 0X7F696782 , & WrapI_U < sceMp3GetMp3ChannelNum > , " sceMp3GetMp3ChannelNum " , ' i ' , " x " } ,
{ 0X87677E40 , & WrapI_U < sceMp3GetBitRate > , " sceMp3GetBitRate " , ' i ' , " x " } ,
{ 0X87C263D1 , & WrapI_U < sceMp3GetMaxOutputSample > , " sceMp3GetMaxOutputSample " , ' i ' , " x " } ,
{ 0X8AB81558 , & WrapU_V < sceMp3StartEntry > , " sceMp3StartEntry " , ' x ' , " " } ,
{ 0X8F450998 , & WrapI_U < sceMp3GetSamplingRate > , " sceMp3GetSamplingRate " , ' i ' , " x " } ,
{ 0XA703FE0F , & WrapI_UUUU < sceMp3GetInfoToAddStreamData > , " sceMp3GetInfoToAddStreamData " , ' i ' , " xxxx " } ,
{ 0XD021C0FB , & WrapI_UU < sceMp3Decode > , " sceMp3Decode " , ' i ' , " xx " } ,
{ 0XD0A56296 , & WrapI_U < sceMp3CheckStreamDataNeeded > , " sceMp3CheckStreamDataNeeded " , ' i ' , " x " } ,
{ 0XD8F54A51 , & WrapI_U < sceMp3GetLoopNum > , " sceMp3GetLoopNum " , ' i ' , " x " } ,
{ 0XF5478233 , & WrapI_U < sceMp3ReleaseMp3Handle > , " sceMp3ReleaseMp3Handle " , ' i ' , " x " } ,
{ 0XAE6D2027 , & WrapU_U < sceMp3GetMPEGVersion > , " sceMp3GetMPEGVersion " , ' x ' , " x " } ,
{ 0X3548AEC8 , & WrapU_U < sceMp3GetFrameNum > , " sceMp3GetFrameNum " , ' x ' , " x " } ,
{ 0X0840E808 , & WrapU_UI < sceMp3ResetPlayPositionByFrame > , " sceMp3ResetPlayPositionByFrame " , ' x ' , " xi " } ,
{ 0X1B839B83 , & WrapU_U < sceMp3LowLevelInit > , " sceMp3LowLevelInit " , ' x ' , " x " } ,
{ 0XE3EE2C81 , & WrapU_UUUUU < sceMp3LowLevelDecode > , " sceMp3LowLevelDecode " , ' x ' , " xxxxx " }
2013-05-06 13:09:40 +00:00
} ;
2013-01-20 13:30:16 +00:00
void Register_sceMp3 ( ) {
2013-05-06 13:09:40 +00:00
RegisterModule ( " sceMp3 " , ARRAY_SIZE ( sceMp3 ) , sceMp3 ) ;
2013-05-12 18:13:07 +00:00
}