mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-25 17:19:42 +00:00
Add support for new atrac3plus decoder
This commit is contained in:
parent
9832e24e8a
commit
b0a3f803e0
@ -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" />
|
||||
|
@ -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" />
|
||||
|
@ -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
80
Core/HW/atrac3plus.cpp
Normal 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
83
Core/HW/atrac3plus.h
Normal 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_
|
Loading…
Reference in New Issue
Block a user