mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-08-03 03:28:54 -06:00
actually make an attempt at decoding AAC
this code stinks
This commit is contained in:
@ -16,7 +16,8 @@
|
|||||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <algorithm>
|
// TODO move faad stuff to Platform
|
||||||
|
#include <neaacdec.h>
|
||||||
|
|
||||||
#include "../DSi.h"
|
#include "../DSi.h"
|
||||||
#include "AACUcode.h"
|
#include "AACUcode.h"
|
||||||
@ -31,11 +32,26 @@ using Platform::LogLevel;
|
|||||||
namespace DSP_HLE
|
namespace DSP_HLE
|
||||||
{
|
{
|
||||||
|
|
||||||
|
NeAACDecHandle AACDec;
|
||||||
|
|
||||||
|
|
||||||
AACUcode::AACUcode(melonDS::DSi& dsi, int version) : UcodeBase(dsi)
|
AACUcode::AACUcode(melonDS::DSi& dsi, int version) : UcodeBase(dsi)
|
||||||
{
|
{
|
||||||
DSi.RegisterEventFuncs(Event_DSi_DSPHLE, this, {MakeEventThunk(AACUcode, FinishCmd)});
|
DSi.RegisterEventFuncs(Event_DSi_DSPHLE, this, {MakeEventThunk(AACUcode, FinishCmd)});
|
||||||
|
|
||||||
|
AACDec = NeAACDecOpen();
|
||||||
|
|
||||||
|
NeAACDecConfiguration* cfg = NeAACDecGetCurrentConfiguration(AACDec);
|
||||||
|
cfg->defObjectType = LC;
|
||||||
|
cfg->defSampleRate = 48000;
|
||||||
|
cfg->outputFormat = FAAD_FMT_16BIT;
|
||||||
|
NeAACDecSetConfiguration(AACDec, cfg);
|
||||||
|
|
||||||
|
/*unsigned long freq = 48000;
|
||||||
|
unsigned char chan = 2;
|
||||||
|
int res = NeAACDecInit(AACDec, nullptr, 234, &freq, &chan);
|
||||||
|
printf("init = %d\n", res);*/
|
||||||
|
|
||||||
if (version == -1)
|
if (version == -1)
|
||||||
Log(LogLevel::Info, "DSP_HLE: initializing AAC decoder ucode (DSi sound app)\n");
|
Log(LogLevel::Info, "DSP_HLE: initializing AAC decoder ucode (DSi sound app)\n");
|
||||||
else
|
else
|
||||||
@ -44,6 +60,8 @@ AACUcode::AACUcode(melonDS::DSi& dsi, int version) : UcodeBase(dsi)
|
|||||||
|
|
||||||
AACUcode::~AACUcode()
|
AACUcode::~AACUcode()
|
||||||
{
|
{
|
||||||
|
NeAACDecClose(AACDec);
|
||||||
|
|
||||||
DSi.UnregisterEventFuncs(Event_DSi_DSPHLE);
|
DSi.UnregisterEventFuncs(Event_DSi_DSPHLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,6 +73,10 @@ void AACUcode::Reset()
|
|||||||
CmdIndex = 0;
|
CmdIndex = 0;
|
||||||
CmdParamCount = 0;
|
CmdParamCount = 0;
|
||||||
memset(CmdParams, 0, sizeof(CmdParams));
|
memset(CmdParams, 0, sizeof(CmdParams));
|
||||||
|
|
||||||
|
memset(FrameBuf, 0, sizeof(FrameBuf));
|
||||||
|
memset(LeftOutput, 0, sizeof(LeftOutput));
|
||||||
|
memset(RightOutput, 0, sizeof(RightOutput));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AACUcode::DoSavestate(Savestate *file)
|
void AACUcode::DoSavestate(Savestate *file)
|
||||||
@ -71,7 +93,7 @@ void AACUcode::SendData(u8 index, u16 val)
|
|||||||
|
|
||||||
if (index == 1)
|
if (index == 1)
|
||||||
{
|
{
|
||||||
printf("-- CMD1 = %04X, state=%d cmd=%d count=%d\n", val, CmdState,CmdIndex, CmdParamCount);
|
//printf("-- CMD1 = %04X, state=%d cmd=%d count=%d\n", val, CmdState,CmdIndex, CmdParamCount);
|
||||||
RecvCmdWord();
|
RecvCmdWord();
|
||||||
}
|
}
|
||||||
else if (index == 2)
|
else if (index == 2)
|
||||||
@ -105,10 +127,7 @@ void AACUcode::RecvCmdWord()
|
|||||||
// might be different depending on sample rate etc
|
// might be different depending on sample rate etc
|
||||||
|
|
||||||
CmdState = 2;
|
CmdState = 2;
|
||||||
|
CmdDecodeFrame();
|
||||||
// TODO actually decode shit
|
|
||||||
|
|
||||||
DSi.ScheduleEvent(Event_DSi_DSPHLE, false, 115000, 0, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -116,6 +135,134 @@ void AACUcode::RecvCmdWord()
|
|||||||
|
|
||||||
CmdWritten[1] = false;
|
CmdWritten[1] = false;
|
||||||
}
|
}
|
||||||
|
int pett = 0;
|
||||||
|
void AACUcode::CmdDecodeFrame()
|
||||||
|
{
|
||||||
|
u16 framelen = CmdParams[0];
|
||||||
|
u32 freq = (CmdParams[1] << 16) | CmdParams[2];
|
||||||
|
u16 chan = CmdParams[3];
|
||||||
|
u32 frameaddr = (CmdParams[4] << 16) | CmdParams[5];
|
||||||
|
u32 leftaddr = (CmdParams[6] << 16) | CmdParams[7];
|
||||||
|
u32 rightaddr = (CmdParams[8] << 16) | CmdParams[9];
|
||||||
|
|
||||||
|
printf("AAC: len=%d freq=%d chan=%d in=%08X out=%08X/%08X\n",
|
||||||
|
framelen, freq, chan, frameaddr, leftaddr, rightaddr);
|
||||||
|
|
||||||
|
// verify the parameters
|
||||||
|
bool fail = false;
|
||||||
|
|
||||||
|
if ((framelen == 0) || (framelen > 1700))
|
||||||
|
fail = true;
|
||||||
|
if ((freq == 0) || (freq > 48000))
|
||||||
|
fail = true;
|
||||||
|
if ((chan != 1) && (chan != 2))
|
||||||
|
fail = true;
|
||||||
|
if (frameaddr == 0)
|
||||||
|
fail = true;
|
||||||
|
if (leftaddr == 0)
|
||||||
|
fail = true;
|
||||||
|
if ((chan != 1) && (rightaddr == 0))
|
||||||
|
fail = true;
|
||||||
|
|
||||||
|
// check input frequency
|
||||||
|
// this isn't entirely accurate
|
||||||
|
// in the ucode, any frequency not within the list below causes an init failure
|
||||||
|
// but the return value from the init function is ignored
|
||||||
|
u32 freqlist[9] = {48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000};
|
||||||
|
u8 freqnum = 0xF;
|
||||||
|
for (int i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
if (freq == freqlist[i])
|
||||||
|
{
|
||||||
|
freqnum = 3 + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (freqnum == 0xF)
|
||||||
|
fail = true;
|
||||||
|
|
||||||
|
if (fail)
|
||||||
|
{
|
||||||
|
// end the command with return code 1 (invalid parameters)
|
||||||
|
DSi.ScheduleEvent(Event_DSi_DSPHLE, false, 256, 0, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("AAC: good, freq=%d\n", freqnum);
|
||||||
|
|
||||||
|
// make an ADTS header
|
||||||
|
/*
|
||||||
|
* u32 adts[2];
|
||||||
|
int freq = 4;
|
||||||
|
int ch = 2;
|
||||||
|
int framelen = fs & 0x1FFF;
|
||||||
|
int resv = 0x7FF;
|
||||||
|
databotte[0] = 0xFF;
|
||||||
|
databotte[1] = 0xF1;
|
||||||
|
databotte[2] = 0x40 | (freq << 2) | (ch >> 2); // freq
|
||||||
|
databotte[3] = (ch << 6) | (fs >> 11);
|
||||||
|
databotte[4] = (framelen >> 3);
|
||||||
|
databotte[5] = (framelen << 5) | (resv >> 6);
|
||||||
|
databotte[6] = (resv << 2);*/
|
||||||
|
u32 totallen = framelen + 7;
|
||||||
|
u32 rsv = 0x7FF;
|
||||||
|
FrameBuf[0] = 0xFF;
|
||||||
|
FrameBuf[1] = 0xF1;
|
||||||
|
FrameBuf[2] = 0x40 | (freqnum << 2) | (chan >> 2);
|
||||||
|
FrameBuf[3] = (chan << 6) | (totallen >> 11);
|
||||||
|
FrameBuf[4] = (totallen >> 3);
|
||||||
|
FrameBuf[5] = (totallen << 5) | (rsv >> 6);
|
||||||
|
FrameBuf[6] = (rsv << 2);
|
||||||
|
|
||||||
|
#define databotte FrameBuf
|
||||||
|
printf("%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||||
|
databotte[0],databotte[1],databotte[2],databotte[3],
|
||||||
|
databotte[4],databotte[5],databotte[6]);
|
||||||
|
|
||||||
|
// read frame data
|
||||||
|
//ReadARM9Mem((u16*)&FrameBuf[7], frameaddr, framelen);
|
||||||
|
for (int i = 0; i < framelen; i++)
|
||||||
|
{
|
||||||
|
FrameBuf[7+i] = DSi.ARM9Read8(frameaddr + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// init
|
||||||
|
// TODO only do if config changed!
|
||||||
|
if (pett < 2)
|
||||||
|
{
|
||||||
|
if (pett == 1)
|
||||||
|
{
|
||||||
|
unsigned long _freq = 0;
|
||||||
|
unsigned char _chan = 0;
|
||||||
|
int res = NeAACDecInit(AACDec, FrameBuf, totallen, &_freq, &_chan);
|
||||||
|
printf("init = %d, %ld, %d\n", res, _freq, _chan);
|
||||||
|
}
|
||||||
|
pett++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// decode
|
||||||
|
NeAACDecFrameInfo finfo;
|
||||||
|
/*void* samplebuf[2] = {LeftOutput, RightOutput};
|
||||||
|
NeAACDecDecode2(AACDec, &finfo, FrameBuf, totallen, samplebuf, 1024*4);
|
||||||
|
printf("decode res = %d %d %d\n", finfo.error, finfo.bytesconsumed, finfo.samples);
|
||||||
|
|
||||||
|
WriteARM9Mem((u16*)LeftOutput, leftaddr, 1024*2);
|
||||||
|
WriteARM9Mem((u16*)RightOutput, rightaddr, 1024*2); // checkme*/
|
||||||
|
s16* dataout = (s16*)NeAACDecDecode(AACDec, &finfo, FrameBuf, totallen);
|
||||||
|
printf("decode res = %p %d %d/%d %d\n", dataout, finfo.error, (int)finfo.bytesconsumed, totallen, (int)finfo.samples);
|
||||||
|
if (dataout)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 1024; i++)
|
||||||
|
{
|
||||||
|
DSi.ARM9Write16(leftaddr, *dataout++);
|
||||||
|
DSi.ARM9Write16(rightaddr, *dataout++);
|
||||||
|
leftaddr += 2;
|
||||||
|
rightaddr += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DSi.ScheduleEvent(Event_DSi_DSPHLE, false, 115000, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void AACUcode::FinishCmd(u32 param)
|
void AACUcode::FinishCmd(u32 param)
|
||||||
{
|
{
|
||||||
@ -123,6 +270,9 @@ void AACUcode::FinishCmd(u32 param)
|
|||||||
CmdParamCount = 0;
|
CmdParamCount = 0;
|
||||||
|
|
||||||
SendReply(0, param);
|
SendReply(0, param);
|
||||||
|
|
||||||
|
if (CmdWritten[1])
|
||||||
|
RecvCmdWord();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,7 +43,12 @@ protected:
|
|||||||
u8 CmdParamCount;
|
u8 CmdParamCount;
|
||||||
u16 CmdParams[10];
|
u16 CmdParams[10];
|
||||||
|
|
||||||
|
u8 FrameBuf[1707];
|
||||||
|
s16 LeftOutput[1024];
|
||||||
|
s16 RightOutput[1024];
|
||||||
|
|
||||||
void RecvCmdWord();
|
void RecvCmdWord();
|
||||||
|
void CmdDecodeFrame();
|
||||||
void FinishCmd(u32 param);
|
void FinishCmd(u32 param);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -589,8 +589,7 @@ void DSi_DSP::Write8(u32 addr, u8 val)
|
|||||||
// no REPx writes
|
// no REPx writes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool fazil = false;
|
|
||||||
int state = 0; u32 aacaddr=0; u32 aaclen = 0;
|
|
||||||
void DSi_DSP::Write16(u32 addr, u16 val)
|
void DSi_DSP::Write16(u32 addr, u16 val)
|
||||||
{
|
{
|
||||||
Log(LogLevel::Debug,"DSP WRITE16 %d %08X %08X %08X\n", IsDSPCoreEnabled(), addr, val, DSi.GetPC(0));
|
Log(LogLevel::Debug,"DSP WRITE16 %d %08X %08X %08X\n", IsDSPCoreEnabled(), addr, val, DSi.GetPC(0));
|
||||||
@ -646,45 +645,17 @@ void DSi_DSP::Write16(u32 addr, u16 val)
|
|||||||
// SEM not writable
|
// SEM not writable
|
||||||
|
|
||||||
case 0x20: // CMD0
|
case 0x20: // CMD0
|
||||||
DSP_CMD[0] = val;printf("DSP: CMD0 = %04X\n", val);
|
DSP_CMD[0] = val;
|
||||||
if (DSPCore)
|
if (DSPCore)
|
||||||
DSPCore->SendData(0, val);
|
DSPCore->SendData(0, val);
|
||||||
break;
|
break;
|
||||||
case 0x28: // CMD1
|
case 0x28: // CMD1
|
||||||
DSP_CMD[1] = val;printf("DSP: CMD1 = %04X\n", val);
|
DSP_CMD[1] = val;
|
||||||
if (DSPCore)
|
if (DSPCore)
|
||||||
DSPCore->SendData(1, val);
|
DSPCore->SendData(1, val);
|
||||||
{
|
|
||||||
if (state==0 && val==1)
|
|
||||||
{
|
|
||||||
state = 1;
|
|
||||||
}
|
|
||||||
else if (state > 0)
|
|
||||||
{
|
|
||||||
if (state==1) aaclen = val;
|
|
||||||
if (state==5) aacaddr = val << 16;
|
|
||||||
if (state==6) aacaddr |= val;
|
|
||||||
if (state==10)
|
|
||||||
{
|
|
||||||
printf("AAC FRAME: addr=%08X len=%08X\n", aacaddr, aaclen);
|
|
||||||
|
|
||||||
for (int i = 0; i < aaclen; i+=16)
|
|
||||||
{
|
|
||||||
printf("%08X: ", i);
|
|
||||||
int l = 16;
|
|
||||||
if ((i+l) > aaclen) l = aaclen-i;
|
|
||||||
for (int j = 0; j < l; j++)
|
|
||||||
printf("%02X ", DSi.ARM9Read8(aacaddr+i+j));
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state++;
|
|
||||||
if (state>10) state = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 0x30: // CMD2
|
case 0x30: // CMD2
|
||||||
DSP_CMD[2] = val;printf("DSP: CMD2 = %04X\n", val);
|
DSP_CMD[2] = val;
|
||||||
if (DSPCore)
|
if (DSPCore)
|
||||||
DSPCore->SendData(2, val);
|
DSPCore->SendData(2, val);
|
||||||
break;
|
break;
|
||||||
|
@ -837,7 +837,7 @@ void DSi_MMCStorage::Reset()
|
|||||||
memset(SCR, 0, 8);
|
memset(SCR, 0, 8);
|
||||||
*(u32*)&SCR[0] = 0x012A0000;
|
*(u32*)&SCR[0] = 0x012A0000;
|
||||||
|
|
||||||
memset(SSR, 0, 64);
|
memset(SD_SSR, 0, 64);
|
||||||
|
|
||||||
BlockSize = 0;
|
BlockSize = 0;
|
||||||
RWAddress = 0;
|
RWAddress = 0;
|
||||||
@ -855,7 +855,7 @@ void DSi_MMCStorage::DoSavestate(Savestate* file)
|
|||||||
file->Var32(&OCR);
|
file->Var32(&OCR);
|
||||||
file->Var32(&RCA);
|
file->Var32(&RCA);
|
||||||
file->VarArray(SCR, 8);
|
file->VarArray(SCR, 8);
|
||||||
file->VarArray(SSR, 64);
|
file->VarArray(SD_SSR, 64);
|
||||||
|
|
||||||
file->Var32(&BlockSize);
|
file->Var32(&BlockSize);
|
||||||
file->Var64(&RWAddress);
|
file->Var64(&RWAddress);
|
||||||
@ -1014,7 +1014,7 @@ void DSi_MMCStorage::SendACMD(u8 cmd, u32 param)
|
|||||||
|
|
||||||
case 13: // get SSR
|
case 13: // get SSR
|
||||||
Host->SendResponse(CSR, true);
|
Host->SendResponse(CSR, true);
|
||||||
Host->DataRX(SSR, 64);
|
Host->DataRX(SD_SSR, 64);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 41: // set operating conditions
|
case 41: // set operating conditions
|
||||||
|
@ -200,7 +200,7 @@ private:
|
|||||||
u32 OCR;
|
u32 OCR;
|
||||||
u32 RCA;
|
u32 RCA;
|
||||||
u8 SCR[8];
|
u8 SCR[8];
|
||||||
u8 SSR[64];
|
u8 SD_SSR[64];
|
||||||
|
|
||||||
u32 BlockSize;
|
u32 BlockSize;
|
||||||
u64 RWAddress;
|
u64 RWAddress;
|
||||||
|
@ -181,6 +181,7 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
target_link_libraries(melonDS PRIVATE core)
|
target_link_libraries(melonDS PRIVATE core)
|
||||||
target_link_libraries(melonDS PRIVATE PkgConfig::SDL2 PkgConfig::LibArchive PkgConfig::Zstd)
|
target_link_libraries(melonDS PRIVATE PkgConfig::SDL2 PkgConfig::LibArchive PkgConfig::Zstd)
|
||||||
|
target_link_libraries(melonDS PRIVATE faad) # temporary hack
|
||||||
target_link_libraries(melonDS PRIVATE ${QT_LINK_LIBS} ${CMAKE_DL_LIBS})
|
target_link_libraries(melonDS PRIVATE ${QT_LINK_LIBS} ${CMAKE_DL_LIBS})
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
Reference in New Issue
Block a user