112 lines
2.6 KiB
C++
112 lines
2.6 KiB
C++
#include "neaacdec.h"
|
|
|
|
#include "Platform.h"
|
|
|
|
// mostly a copy paste from melonDS/src/frontend/qt_sdl/Platform_AAC.cpp
|
|
|
|
namespace melonDS::Platform
|
|
{
|
|
|
|
struct AACDecoder
|
|
{
|
|
NeAACDecHandle handle;
|
|
bool configured;
|
|
};
|
|
|
|
AACDecoder* AAC_Init()
|
|
{
|
|
AACDecoder* dec = new AACDecoder();
|
|
dec->handle = NeAACDecOpen();
|
|
|
|
if (!dec->handle)
|
|
{
|
|
delete dec;
|
|
return nullptr;
|
|
}
|
|
|
|
auto* cfg = NeAACDecGetCurrentConfiguration(dec->handle);
|
|
cfg->defObjectType = LC;
|
|
cfg->outputFormat = FAAD_FMT_16BIT;
|
|
|
|
if (!NeAACDecSetConfiguration(dec->handle, cfg))
|
|
{
|
|
NeAACDecClose(dec->handle);
|
|
delete dec;
|
|
return nullptr;
|
|
}
|
|
|
|
dec->configured = false;
|
|
return dec;
|
|
}
|
|
|
|
void AAC_DeInit(AACDecoder* dec)
|
|
{
|
|
NeAACDecClose(dec->handle);
|
|
delete dec;
|
|
}
|
|
|
|
bool AAC_Configure(AACDecoder* dec, int frequency, int channels)
|
|
{
|
|
// see get_sample_rate in faad2/libfaad/common.c
|
|
constexpr u32 freqList[9] = { 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000 };
|
|
u8 freqNum = 3; // default to 48000
|
|
for (u32 i = 0; i < 9; i++)
|
|
{
|
|
if (frequency == freqList[i])
|
|
{
|
|
freqNum = 3 + i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Produce an MP4 ASC to configure the decoder
|
|
// Basic MP4 ASC format is as follows:
|
|
// 5 bits: Object Type Index (always LC (2) here)
|
|
// 4 bits: Sample frequency index (DSi only supports up to 48000Hz)
|
|
// 4 bits: Channel count
|
|
// 1 bit: Frame Length flag (never true here)
|
|
// 1 bit: Core coder delay present (never true here)
|
|
// 1 bit: Extension flag (never true here)
|
|
// 11 bits: Sync extension type (0x2B7 indicates possible SBR specification)
|
|
// 5 bits: Extension audio object type (5 indicates SBR specification)
|
|
// 1 bit: SBR present (never present on DSi, which doesn't support such)
|
|
|
|
u8 asc[5];
|
|
asc[0] = ((LC << 3) & 0b1111000) | ((freqNum >> 1) & 0b00000111);
|
|
asc[1] = ((freqNum << 7) & 0b10000000) | ((channels << 3) & 0b01111000);
|
|
asc[2] = (0x2B7 >> 3) & 0b11111111;
|
|
asc[3] = ((0x2B7 << 5) & 0b11100000) | (0x05 & 0b00011111);
|
|
asc[4] = (0x00 << 7) & 0b10000000;
|
|
|
|
unsigned long freqOut;
|
|
unsigned char chanOut;
|
|
if (NeAACDecInit2(dec->handle, asc, sizeof(asc), &freqOut, &chanOut) != 0)
|
|
{
|
|
dec->configured = false;
|
|
return false;
|
|
}
|
|
|
|
dec->configured = true;
|
|
return true;
|
|
}
|
|
|
|
bool AAC_DecodeFrame(AACDecoder* dec, const void* input, int inputlen, void* output, int outputlen)
|
|
{
|
|
if (!dec->configured)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
NeAACDecFrameInfo frameInfo;
|
|
NeAACDecDecode2(dec->handle, &frameInfo, (unsigned char*)input, inputlen, &output, outputlen);
|
|
|
|
if (frameInfo.error != 0 || frameInfo.bytesconsumed != inputlen)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|