Add support for new atrac3plus decoder

This commit is contained in:
oioitff 2013-05-30 17:33:47 +08:00
parent 9832e24e8a
commit b0a3f803e0
5 changed files with 266 additions and 9 deletions

View File

@ -228,6 +228,7 @@
<ClCompile Include="HLE\sceVaudio.cpp" />
<ClCompile Include="HLE\__sceAudio.cpp" />
<ClCompile Include="Host.cpp" />
<ClCompile Include="HW\atrac3plus.cpp" />
<ClCompile Include="HW\audioPlayer.cpp" />
<ClCompile Include="HW\MediaEngine.cpp" />
<ClCompile Include="HW\MemoryStick.cpp" />
@ -406,6 +407,7 @@
<ClInclude Include="HLE\sceVaudio.h" />
<ClInclude Include="HLE\__sceAudio.h" />
<ClInclude Include="Host.h" />
<ClInclude Include="HW\atrac3plus.h" />
<ClInclude Include="HW\audioPlayer.h" />
<ClInclude Include="HW\MediaEngine.h" />
<ClInclude Include="HW\OMAConvert.h" />

View File

@ -427,6 +427,9 @@
<ClCompile Include="MIPS\JitCommon\JitBlockCache.cpp">
<Filter>MIPS\JitCommon</Filter>
</ClCompile>
<ClCompile Include="HW\atrac3plus.cpp">
<Filter>HW</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ELF\ElfReader.h">
@ -792,6 +795,9 @@
<ClInclude Include="MIPS\JitCommon\JitBlockCache.h">
<Filter>MIPS\JitCommon</Filter>
</ClInclude>
<ClInclude Include="HW\atrac3plus.h">
<Filter>HW</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />

View File

@ -78,6 +78,8 @@ extern "C" {
#include "../HW/audioPlayer.h"
#endif // _USE_DSHOW_
#include "Core/HW/atrac3plus.h"
struct InputBuffer {
u32 addr;
u32 size;
@ -114,6 +116,8 @@ struct Atrac {
pSwrCtx = 0;
pFrame = 0;
#endif // USE_FFMPEG
decoder_context = 0;
sampleQueue.empty();
}
~Atrac() {
@ -132,6 +136,9 @@ struct Atrac {
if (data_buf)
delete [] data_buf;
data_buf = 0;
Atrac3plus_Decoder::closeContext(&decoder_context);
sampleQueue.empty();
}
void DoState(PointerWrap &p) {
@ -178,7 +185,8 @@ struct Atrac {
void Analyze();
u32 getDecodePosBySample(int sample) {
return (u32)(firstSampleoffset + sample / ATRAC_MAX_SAMPLES * atracBytesPerFrame );
int atracSamplesPerFrame = (codeType == PSP_MODE_AT_3_PLUS ? 0x800 : 0x400);
return (u32)(firstSampleoffset + sample / atracSamplesPerFrame * atracBytesPerFrame );
}
int getRemainFrames() {
@ -227,6 +235,9 @@ struct Atrac {
InputBuffer first;
InputBuffer second;
Atrac3plus_Decoder::BufferQueue sampleQueue;
void* decoder_context;
#ifdef USE_FFMPEG
AVFormatContext *pFormatCtx;
AVIOContext *pAVIOCtx;
@ -276,6 +287,7 @@ void __AtracInit() {
initaudioEngine();
#endif //_USE_DSHOW_
Atrac3plus_Decoder::initdecoder();
}
void __AtracDoState(PointerWrap &p) {
@ -293,6 +305,8 @@ void __AtracShutdown() {
#ifdef _USE_DSHOW_
shutdownEngine();
#endif // _USE_DSHOW_
Atrac3plus_Decoder::shutdowndecoder();
}
Atrac *getAtrac(int atracID) {
@ -548,6 +562,35 @@ u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32 finishF
} else
#endif // USE_FFMPEG
if (atrac->decoder_context) {
static u8 buf[0x8000];
if (atrac->sampleQueue.getQueueSize() < ATRAC_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels) {
int decodebytes = 0;
atrac->decodePos = atrac->getDecodePosBySample(atrac->currentSample);
int inbytes = std::max((int)atrac->first.filesize - (int)atrac->decodePos, 0);
inbytes = std::min(inbytes, (int)atrac->atracBytesPerFrame);
if (inbytes > 0) {
Atrac3plus_Decoder::atrac3plus_decode(atrac->decoder_context, atrac->data_buf + atrac->decodePos, inbytes, &decodebytes, buf);
INFO_LOG(HLE, "decodebytes: %i outbuf: %08x", decodebytes, buf);
atrac->sampleQueue.push(buf, decodebytes);
}
}
s16* out = (s16*)Memory::GetPointer(outAddr);
memset(out, 0, ATRAC_MAX_SAMPLES * sizeof(s16) * atrac->atracOutputChannels);
int gotsize = atrac->sampleQueue.pop_front(buf, ATRAC_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels);
numSamples = gotsize / sizeof(s16) / atrac->atracChannels;
s16* in = (s16*)buf;
for (int i = 0; i < numSamples; i++) {
s16 sampleL = *in++;
s16 sampleR = sampleL;
if (atrac->atracChannels == 2)
sampleR = *in++;
*out++ = sampleL;
if (atrac->atracOutputChannels == 2)
*out++ = sampleR;
}
numSamples = ATRAC_MAX_SAMPLES;
} else
#ifdef _USE_DSHOW_
if (engine) {
static s16 buf[ATRAC_MAX_SAMPLES * 2];
@ -899,6 +942,11 @@ int64_t _AtracSeekbuffer(void *opaque, int64_t offset, int whence)
int __AtracSetContext(Atrac *atrac)
{
if (atrac->codeType == PSP_MODE_AT_3_PLUS) {
atrac->decoder_context = Atrac3plus_Decoder::openContext();
return 0;
}
#ifdef _USE_DSHOW_
if (atrac->codeType == PSP_MODE_AT_3_PLUS && atrac->atracChannels != 1) {
addAtrac3Audio(atrac->data_buf, atrac->first.size, atrac->atracID);
@ -1007,17 +1055,15 @@ int _AtracSetData(Atrac *atrac, u32 buffer, u32 bufferSize)
} else if (atrac->codeType == PSP_MODE_AT_3_PLUS) {
if (atrac->atracChannels == 1) {
WARN_LOG(HLE, "This is an atrac3+ mono audio (Unsupported)");
WARN_LOG(HLE, "This is an atrac3+ mono audio");
} else {
WARN_LOG(HLE, "This is an atrac3+ stereo audio");
#ifdef _USE_DSHOW_
atrac->data_buf = new u8[atrac->first.filesize];
Memory::Memcpy(atrac->data_buf, buffer, std::min(bufferSize, atrac->first.filesize));
return __AtracSetContext(atrac);
#endif // _USE_DSHOW
}
atrac->data_buf = new u8[atrac->first.filesize];
Memory::Memcpy(atrac->data_buf, buffer, std::min(bufferSize, atrac->first.filesize));
return __AtracSetContext(atrac);
}
@ -1366,6 +1412,12 @@ int sceAtracLowLevelInitDecoder(int atracID, u32 paramsAddr)
return 0;
}
#endif // USE_FFMPEG
if (atrac->codeType == PSP_MODE_AT_3_PLUS){
atrac->data_buf = new u8[atrac->atracBytesPerFrame];
__AtracSetContext(atrac);
return 0;
}
}
return 0;
}
@ -1432,6 +1484,40 @@ int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesConsumedA
}
#endif // USE_FFMPEG
if (Memory::IsValidAddress(sourceAddr) && Memory::IsValidAddress(sourceBytesConsumedAddr) &&
Memory::IsValidAddress(samplesAddr) && Memory::IsValidAddress(sampleBytesAddr) && atrac && atrac->decoder_context) {
u32 sourcebytes = atrac->first.writableBytes;
static u8 buf[0x8000];
if (sourcebytes > 0) {
int decodebytes = 0;
Atrac3plus_Decoder::atrac3plus_decode(atrac->decoder_context, Memory::GetPointer(sourceAddr), sourcebytes, &decodebytes, buf);
atrac->sampleQueue.push(buf, decodebytes);
}
s16* out = (s16*)Memory::GetPointer(samplesAddr);
memset(out, 0, ATRAC_MAX_SAMPLES * sizeof(s16) * atrac->atracOutputChannels);
int gotsize = atrac->sampleQueue.pop_front(buf, ATRAC_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels);
int numSamples = gotsize / sizeof(s16) / atrac->atracChannels;
s16* in = (s16*)buf;
for (int i = 0; i < numSamples; i++) {
s16 sampleL = *in++;
s16 sampleR = sampleL;
if (atrac->atracChannels == 2)
sampleR = *in++;
*out++ = sampleL;
if (atrac->atracOutputChannels == 2)
*out++ = sampleR;
}
numSamples = ATRAC_MAX_SAMPLES;
Memory::Write_U32(numSamples * sizeof(s16) * atrac->atracOutputChannels, sampleBytesAddr);
int space = atrac->sampleQueue.getQueueSize();
if (space < ATRAC_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels)
atrac->first.writableBytes = atrac->atracBytesPerFrame;
else
atrac->first.writableBytes = 0;
Memory::Write_U32(atrac->first.writableBytes, sourceBytesConsumedAddr);
return 0;
}
#ifdef _USE_DSHOW_
if (Memory::IsValidAddress(sourceAddr) && Memory::IsValidAddress(sourceBytesConsumedAddr) && atrac) {
u32 sourcebytes = Memory::Read_U32(sourceBytesConsumedAddr);

80
Core/HW/atrac3plus.cpp Normal file
View File

@ -0,0 +1,80 @@
#ifdef _WIN32
#include <Windows.h>
#endif // _WIN32
#include <string.h>
namespace Atrac3plus_Decoder {
#ifdef _WIN32
HMODULE hlib = 0;
#endif // _WIN32
typedef int (* ATRAC3PLUS_DECODEFRAME)(void* context, void* inbuf, int inbytes, int* channels, void** outbuf);
typedef void* (* ATRAC3PLUS_OPENCONTEXT)();
typedef int (* ATRAC3PLUS_CLOSECONTEXT)(void* context);
ATRAC3PLUS_DECODEFRAME frame_decoder = 0;
ATRAC3PLUS_OPENCONTEXT open_context = 0;
ATRAC3PLUS_CLOSECONTEXT close_context = 0;
int initdecoder() {
#ifdef _WIN32
hlib = LoadLibraryA("MaiAT3PlusDecoder.dll");
if (hlib) {
frame_decoder = (ATRAC3PLUS_DECODEFRAME)GetProcAddress(hlib, "Atrac3plusDecoder_decodeFrame");
open_context = (ATRAC3PLUS_OPENCONTEXT)GetProcAddress(hlib, "Atrac3plusDecoder_openContext");
close_context = (ATRAC3PLUS_CLOSECONTEXT)GetProcAddress(hlib, "Atrac3plusDecoder_closeContext");
} else {
return -1;
}
#endif // _WIN32
return 0;
}
int shutdowndecoder() {
#ifdef _WIN32
if (hlib) {
FreeLibrary(hlib);
hlib = 0;
}
#endif // _WIN32
return 0;
}
void* openContext() {
if (!open_context)
return 0;
return open_context();
}
int closeContext(void** context) {
if (!close_context || !context)
return 0;
close_context(*context);
*context = 0;
return 0;
}
bool atrac3plus_decode(void* context, void* inbuf, int inbytes, int *outbytes, void* outbuf) {
if (!frame_decoder) {
*outbytes = 0;
return false;
}
int channels = 0;
void* buf;
int ret = frame_decoder(context, inbuf, inbytes, &channels, &buf);
if (ret != 0) {
*outbytes = 0;
return false;
}
*outbytes = channels * 2 * 0x800;
memcpy(outbuf, buf, *outbytes);
return true;
}
} // Atrac3plus_Decoder

83
Core/HW/atrac3plus.h Normal file
View File

@ -0,0 +1,83 @@
#ifndef _ATRAC3PLUS_DECODER_
#define _ATRAC3PLUS_DECODER_
namespace Atrac3plus_Decoder {
int initdecoder();
int shutdowndecoder();
void* openContext();
int closeContext(void** context);
bool atrac3plus_decode(void* context, void* inbuf, int inbytes, int *outbytes, void* outbuf);
struct BufferQueue {
BufferQueue(int size = 0x20000) {
bufQueue = 0;
alloc(size);
}
~BufferQueue() {
if (bufQueue)
delete [] bufQueue;
}
bool alloc(int size) {
if (size < 0)
return false;
if (bufQueue)
delete [] bufQueue;
bufQueue = new unsigned char[size];
start = 0;
end = 0;
bufQueueSize = size;
return true;
}
void empty() {
start = 0;
end = 0;
}
inline int getQueueSize() {
return (end + bufQueueSize - start) % bufQueueSize;
}
bool push(unsigned char *buf, int addsize) {
int queuesz = getQueueSize();
int space = bufQueueSize - queuesz;
if (space < addsize || addsize < 0)
return false;
if (end + addsize <= bufQueueSize) {
memcpy(bufQueue + end, buf, addsize);
} else {
int size = bufQueueSize - end;
memcpy(bufQueue + end, buf, size);
memcpy(bufQueue, buf + size, addsize - size);
}
end = (end + addsize) % bufQueueSize;
return true;
}
int pop_front(unsigned char *buf, int wantedsize) {
if (wantedsize <= 0)
return 0;
int bytesgot = getQueueSize();
if (wantedsize < bytesgot)
bytesgot = wantedsize;
if (start + bytesgot <= bufQueueSize) {
memcpy(buf, bufQueue + start, bytesgot);
} else {
int size = bufQueueSize - start;
memcpy(buf, bufQueue + start, size);
memcpy(buf + size, bufQueue, bytesgot - size);
}
start = (start + bytesgot) % bufQueueSize;
return bytesgot;
}
unsigned char* bufQueue;
int start, end;
int bufQueueSize;
};
}
#endif // _ATRAC3PLUS_DECODER_