Files
AnyPS5/core/libs/tests/GuestAudiodec.cpp
T
RickandClaude Opus 5.5 bb95e44e9c fix(libSceAudiodec): decode HE-AAC as the console does
ui_enable_heaac was ignored and FFmpeg applied Parametric Stereo, so an
HE-AAC v2 stream decoded to 48 kHz stereo whatever the flag: 2048
samples in 2 channels per frame, and ERROR_INVALID_PCM_SIZE for a PCM
buffer sized for the console's output. The console returns the 24 kHz
mono core with HE-AAC disabled, and SBR output at 48 kHz in one channel
with it enabled.

AAC access units now reach FFmpeg without their ADTS header, with an
AudioSpecificConfig built from the header or from the raw parameters.
With HE-AAC disabled it signals SBR as absent. With HE-AAC enabled SBR
stays implicit, and a mono stream that FFmpeg decodes to two channels
is reopened with SBR present and Parametric Stereo absent. The new test
decodes fdk-aac HE-AAC v2 and HE-AAC stereo streams, ADTS and raw, with
HE-AAC on and off; it aborts on main.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 17:41:48 +02:00

423 lines
31 KiB
C++

#include "SceTypes.hpp"
#include "prx/libc/include/general/VabiMacros.hpp"
#include <cmath>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <numbers>
#include <vector>
extern "C" {
std::int32_t APS5_VABI sceAudiodecInitLibrary(std::uint32_t);
std::int32_t APS5_VABI sceAudiodecTermLibrary(std::uint32_t);
std::int32_t APS5_VABI sceAudiodecCreateDecoder(AudiodecCtrl*, std::uint32_t);
std::int32_t APS5_VABI sceAudiodecDeleteDecoder(std::int32_t);
std::int32_t APS5_VABI sceAudiodecDecode(std::int32_t, AudiodecCtrl*);
std::int32_t APS5_VABI sceAudiodecClearContext(std::int32_t);
}
static void Require(bool value) { if (!value) std::abort(); }
namespace {
const std::uint8_t AAC_ADTS[] = {
0xFF, 0xF1, 0x4C, 0x80, 0x0F, 0x9F, 0xFC, 0xDC, 0x00, 0x4C, 0x61, 0x76, 0x63, 0x36, 0x33, 0x2E, 0x31, 0x2E, 0x31, 0x30, 0x32, 0x00, 0x42, 0x4D,
0x9F, 0xFF, 0xFF, 0xE1, 0x40, 0xC9, 0xA1, 0xA2, 0xF4, 0x44, 0x23, 0x8E, 0xEA, 0x91, 0x95, 0xA9, 0x2E, 0xE5, 0xDC, 0x92, 0x3B, 0x65, 0xC0, 0xCE,
0xCF, 0x8E, 0x0C, 0xEC, 0xEC, 0xEC, 0xEC, 0xED, 0x59, 0x49, 0x61, 0xBC, 0xA3, 0x44, 0xEA, 0x53, 0xA7, 0x08, 0x22, 0x06, 0x36, 0x6C, 0xD9, 0xB0,
0x64, 0x48, 0xA5, 0x06, 0x36, 0x6C, 0x18, 0x19, 0x10, 0x30, 0x31, 0xB3, 0x66, 0xCD, 0x83, 0x22, 0x45, 0x29, 0xB3, 0x72, 0xCB, 0x14, 0x51, 0x45,
0x14, 0x51, 0x45, 0x14, 0x51, 0x45, 0x40, 0x37, 0xD1, 0x78, 0x8E, 0x3B, 0xAA, 0x46, 0x56, 0xA4, 0xBB, 0x97, 0x72, 0x48, 0xED, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0E, 0xFF, 0xF1, 0x4C, 0x80, 0x18, 0xFF, 0xFC, 0x21, 0x48, 0x6C, 0xFE, 0x7E, 0x7E, 0x7E, 0x47, 0x51, 0x4B, 0xAA, 0xC9, 0x71,
0x64, 0xB8, 0xB2, 0x5C, 0x3F, 0xFE, 0xD7, 0xFD, 0xFE, 0xB8, 0xD3, 0xBF, 0x5D, 0x7F, 0xFD, 0xFF, 0xFA, 0xFD, 0xFA, 0xE3, 0x8D, 0x7C, 0x7F, 0xFE,
0x4F, 0xFA, 0xFD, 0xFA, 0xE3, 0x8D, 0x7E, 0xFF, 0xFF, 0x5F, 0xFD, 0xBE, 0xFD, 0x71, 0xD7, 0x01, 0xB7, 0x49, 0xCD, 0xA0, 0x90, 0x90, 0x96, 0xAF,
0x1B, 0x1C, 0xBC, 0xFB, 0x50, 0x49, 0xFB, 0x71, 0x11, 0x44, 0x26, 0x28, 0x81, 0xA2, 0x53, 0x71, 0x2B, 0xE9, 0x11, 0x4E, 0x3E, 0x9C, 0xF1, 0x14,
0xE3, 0xE9, 0xF4, 0x88, 0xA7, 0x1F, 0x4F, 0xA5, 0x8B, 0x0C, 0x9E, 0x62, 0x69, 0x10, 0xD3, 0x20, 0xBE, 0x58, 0x4A, 0x6D, 0x72, 0x38, 0xAE, 0x2C,
0x4C, 0x51, 0x03, 0x44, 0xA6, 0xE2, 0x57, 0xD2, 0x22, 0x9C, 0x7D, 0x39, 0xE2, 0x29, 0xC7, 0xD3, 0xE9, 0x11, 0x4E, 0x3E, 0x9F, 0x42, 0x38, 0x42,
0x93, 0xE5, 0x39, 0x62, 0x28, 0xA2, 0x88, 0xA2, 0x8A, 0x28, 0xA3, 0x87, 0x6A, 0x1D, 0xE8, 0x77, 0xA1, 0xDE, 0x9F, 0xFF, 0x6B, 0xFE, 0xFF, 0x5C,
0x69, 0xDF, 0xAE, 0xBF, 0xFE, 0xFF, 0xFD, 0x7E, 0xFD, 0x70, 0x7F, 0x8F, 0xFF, 0xC9, 0xFF, 0x5F, 0xBF, 0x5C, 0x1F, 0xF3, 0xFF, 0xF5, 0xFF, 0xDB,
0xEF, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xF1, 0x4C, 0x80, 0x0B, 0xFF, 0xFC, 0x21, 0x77, 0x4F, 0xFF, 0xFF, 0xF0,
0x24, 0x0A, 0xFA, 0x67, 0x34, 0xD7, 0x8E, 0xF7, 0xBC, 0xFF, 0xB7, 0xFE, 0xFA, 0xFA, 0x74, 0xD5, 0xAE, 0xE3, 0xBE, 0x4B, 0x40, 0xEF, 0xBF, 0xBF,
0xBC, 0x2F, 0xFC, 0x7C, 0x7C, 0x66, 0x40, 0xF8, 0xF8, 0xF8, 0x03, 0xDF, 0xDE, 0x11, 0xF1, 0xF0, 0xD8, 0xCF, 0xEF, 0xA0, 0x64, 0xF8, 0x6C, 0x67,
0xF7, 0x84, 0x64, 0xF8, 0x6C, 0x67, 0xF7, 0x29, 0x01, 0xBE, 0x99, 0xCD, 0x35, 0xE3, 0xBD, 0xEF, 0x3F, 0xED, 0xFF, 0xBE, 0xBE, 0x9D, 0x35, 0x6B,
0xB8, 0xEF, 0x92, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xF1, 0x4C, 0x80, 0x0C, 0xFF, 0xFC, 0x21, 0x17, 0x4F, 0xFF, 0xFF, 0xF8, 0x26,
0x0A, 0x88, 0x5D, 0x20, 0xA5, 0x56, 0x67, 0x3F, 0xF6, 0xFF, 0xDF, 0xAE, 0x2E, 0xE5, 0xC9, 0x72, 0x48, 0xE9, 0x90, 0x31, 0xAF, 0x1A, 0xF1, 0xAF,
0xBA, 0xBE, 0xE5, 0xE0, 0x23, 0x2A, 0xCA, 0xBC, 0x6B, 0xC6, 0xBC, 0x6B, 0xC6, 0xBC, 0x6B, 0xC6, 0xBC, 0x6B, 0xC6, 0xB4, 0x69, 0x28, 0xA4, 0x46,
0x92, 0x8A, 0x44, 0x69, 0x28, 0xA4, 0x46, 0x91, 0x1D, 0x24, 0x69, 0x11, 0xA4, 0x47, 0x30, 0x38, 0xF0, 0xE9, 0x05, 0x2A, 0xB3, 0x39, 0xFF, 0xB7,
0xFE, 0xFD, 0x71, 0x77, 0x2E, 0x4B, 0x92, 0x1D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0xFF, 0xF1, 0x4C, 0x80, 0x0C, 0xFF, 0xFC,
0x21, 0x17, 0x4F, 0xFF, 0xFF, 0xF8, 0x28, 0x59, 0xC4, 0xAD, 0x28, 0x99, 0x29, 0xAE, 0xF7, 0xF5, 0x6A, 0xB9, 0x2D, 0x25, 0xC7, 0x5C, 0x92, 0x02,
0x13, 0x42, 0x16, 0x62, 0x16, 0x67, 0x76, 0x6D, 0xDA, 0xA9, 0x9A, 0xBF, 0xE3, 0xC9, 0x27, 0x5E, 0x8A, 0xE4, 0xA6, 0x6A, 0xE4, 0xA5, 0x1C, 0x73,
0x35, 0x9B, 0x46, 0x6D, 0x19, 0xB4, 0x39, 0xA3, 0x36, 0x8C, 0xCD, 0x38, 0xD3, 0x8D, 0x66, 0x69, 0xC6, 0xB3, 0x68, 0xCD, 0xA3, 0x36, 0x8C, 0xDA,
0x33, 0x50, 0x8E, 0x34, 0xA2, 0x64, 0xA6, 0xBB, 0xDF, 0xD5, 0xAA, 0xE4, 0xB4, 0x97, 0x1D, 0x72, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C,
};
const std::uint8_t AAC_RAW_51[] = {
0x00, 0xDE, 0x34, 0xAC, 0xF1, 0x1D, 0x0C, 0x05, 0x89, 0xA2, 0x61, 0x40,
0xB4, 0x4A, 0x37, 0x8D, 0xFF, 0x7F, 0xFD, 0x3F, 0xCF, 0xFB, 0x79, 0xE7,
0xE3, 0xCE, 0x4C, 0x8B, 0x5D, 0xD5, 0xD5, 0x3F, 0xE9, 0x47, 0x6A, 0x5D,
0x69, 0xBA, 0xB1, 0x9A, 0x78, 0xAA, 0x3C, 0xD4, 0xF7, 0xA6, 0xD3, 0x13,
0xCC, 0x21, 0x93, 0x2B, 0x3E, 0x67, 0xDE, 0x74, 0x1A, 0xA3, 0xE7, 0x31,
0xE2, 0x47, 0xE8, 0x68, 0xFB, 0xD5, 0xF6, 0xB5, 0xFC, 0x57, 0xDE, 0x9E,
0x43, 0x6F, 0x3E, 0xF5, 0xF2, 0x1F, 0xBC, 0xFB, 0xC5, 0xBC, 0x53, 0x16,
0xE4, 0x57, 0xAC, 0x64, 0x14, 0xE6, 0x88, 0xAF, 0x66, 0xBA, 0x8C, 0x7A,
0x86, 0xF5, 0x8D, 0xC4, 0xA2, 0x36, 0x89, 0xE3, 0x21, 0xF9, 0xA5, 0x8A,
0xAF, 0xF0, 0xE5, 0x91, 0x2C, 0x15, 0xA2, 0x67, 0xF4, 0x97, 0xDA, 0x40,
0x0A, 0x00, 0x8A, 0x45, 0x7C, 0x92, 0xEA, 0x8F, 0x87, 0x56, 0xC2, 0x40,
0xE1, 0xA2, 0x23, 0x1E, 0x89, 0xE7, 0xBA, 0x61, 0xA3, 0xD5, 0xB9, 0x77,
0x27, 0x13, 0x73, 0x49, 0xE4, 0x98, 0x83, 0x3A, 0x25, 0x86, 0x3A, 0x10,
0x3D, 0x5C, 0xC8, 0xC0, 0x8F, 0xDB, 0x58, 0x50, 0xB0, 0xFB, 0x3F, 0x33,
0xAD, 0xE1, 0xD7, 0xC2, 0xF7, 0xB3, 0x98, 0xDF, 0x39, 0x87, 0xE2, 0x97,
0x34, 0xB4, 0x2A, 0x3A, 0xA0, 0x64, 0x0A, 0x80, 0x76, 0x84, 0xA6, 0x1D,
0x43, 0xF4, 0x0E, 0x12, 0x3E, 0xF2, 0xE2, 0x6A, 0x1F, 0x30, 0xA1, 0xD5,
0xE8, 0x0A, 0x22, 0x39, 0x9E, 0x44, 0xF3, 0xD1, 0x81, 0x6F, 0x49, 0x5A,
0x9C, 0x1F, 0x54, 0xB9, 0x2B, 0xB4, 0x73, 0xA3, 0x8D, 0x74, 0x6F, 0x87,
0x2D, 0x51, 0xCE, 0x3A, 0x39, 0xED, 0x38, 0x49, 0x55, 0x7C, 0x7D, 0xBE,
0xED, 0x65, 0x29, 0xAE, 0x3E, 0xBE, 0x70, 0xD1, 0x08, 0xD2, 0x1B, 0xEC,
0xF0, 0x66, 0x56, 0x8A, 0x03, 0xA9, 0x80, 0xE9, 0x5F, 0x2F, 0xFA, 0x7F,
0xF1, 0xFE, 0xFF, 0xED, 0xE7, 0x9F, 0x8F, 0x3C, 0xEB, 0x37, 0xAC, 0xEA,
0xD9, 0x75, 0x02, 0xD4, 0xDC, 0xDD, 0x45, 0xED, 0x9C, 0x2A, 0x83, 0x34,
0xF1, 0x54, 0xD2, 0x3F, 0xBD, 0x36, 0x98, 0x69, 0x87, 0x04, 0xAA, 0x5F,
0x99, 0xF7, 0x9D, 0x06, 0xA8, 0xF9, 0xCC, 0x78, 0x91, 0xFA, 0x1A, 0x3E,
0xF5, 0x7C, 0xD8, 0xF7, 0x9F, 0x7A, 0x79, 0x0D, 0xD5, 0x45, 0x5C, 0x55,
0x2A, 0x4A, 0xA0, 0x66, 0x59, 0xC6, 0x82, 0x89, 0x66, 0x0C, 0x65, 0xF5,
0xE1, 0xEA, 0xEE, 0xD9, 0x9E, 0x5F, 0x5B, 0xB4, 0xE0, 0x93, 0x0F, 0x11,
0xA2, 0x49, 0xC3, 0x2F, 0xC7, 0xA1, 0x6E, 0x1A, 0x81, 0xFF, 0x57, 0x7D,
0x6F, 0xC3, 0xAB, 0x61, 0x20, 0x70, 0xD1, 0x11, 0x8F, 0x44, 0xEB, 0x3C,
0xF4, 0x60, 0x59, 0xA4, 0xAD, 0x4E, 0x0F, 0x54, 0xB4, 0x5C, 0xDF, 0x67,
0x88, 0x68, 0xA0, 0x3A, 0x9F, 0x0E, 0x95, 0xF2, 0xFF, 0xB7, 0xFE, 0x3F,
0xDF, 0xFD, 0xBC, 0xF3, 0xF1, 0xE7, 0xBE, 0xB2, 0xA6, 0xFA, 0xBA, 0x49,
0x02, 0xD5, 0x6E, 0x6E, 0xA2, 0x61, 0xC2, 0xA8, 0x33, 0x4F, 0x15, 0x4D,
0x23, 0xFB, 0xD3, 0x69, 0x86, 0x6C, 0x70, 0x4A, 0xA5, 0xF9, 0x9F, 0x79,
0xD0, 0x6A, 0x8F, 0x9C, 0xC7, 0x89, 0x1F, 0xA1, 0xA3, 0xEF, 0x57, 0xCD,
0x2D, 0xE7, 0xEF, 0x4F, 0x21, 0xB7, 0x9F, 0x7A, 0xF9, 0x0F, 0xDE, 0x3B,
0xC5, 0xBC, 0x50, 0x0B, 0x33, 0xEB, 0x19, 0x05, 0x39, 0xA2, 0x2B, 0xD9,
0xAE, 0xA3, 0x1D, 0x81, 0xCC, 0x1B, 0xCC, 0x9C, 0xA3, 0x5F, 0x03, 0xE4,
0x96, 0xE6, 0xF8, 0xAC, 0xC0, 0x98, 0x22, 0xA8, 0x3E, 0x29, 0x7A, 0xC8,
0x30, 0xEA, 0xD8, 0x48, 0x1C, 0x34, 0x44, 0x63, 0xD1, 0x39, 0x18, 0xD2,
0x1B, 0xEC, 0xF1, 0x0D, 0x14, 0x07, 0x52, 0xE1, 0xD2, 0xBE, 0x5F, 0xF6,
0xFF, 0xC7, 0xFB, 0xFF, 0xB7, 0x9E, 0x7E, 0x3C, 0xF7, 0xD6, 0x54, 0xDF,
0x57, 0x49, 0x20, 0x5A, 0xAD, 0xCD, 0xD4, 0x4C, 0x6F, 0x85, 0x50, 0x66,
0x9E, 0x2A, 0x9A, 0x47, 0xF7, 0xA6, 0xD3, 0x0C, 0xD8, 0xE0, 0x95, 0x4B,
0xF3, 0x3E, 0xF3, 0xA0, 0xD5, 0x1F, 0x39, 0x8F, 0x12, 0x3F, 0x43, 0x47,
0xDE, 0xAF, 0x9A, 0x5B, 0xCF, 0xDE, 0x9E, 0x43, 0x6F, 0x3E, 0xF5, 0xF2,
0x1F, 0xBC, 0x77, 0x8B, 0x78, 0xA0, 0x16, 0x67, 0xD6, 0x32, 0x0A, 0x73,
0x44, 0x57, 0xB3, 0x5D, 0x46, 0x3B, 0x03, 0x98, 0x37, 0x99, 0x39, 0x46,
0xBE, 0x07, 0xC9, 0x2D, 0xCD, 0xF1, 0x59, 0x81, 0x30, 0x45, 0x50, 0x7C,
0x52, 0xF5, 0x90, 0x61, 0xD5, 0xB0, 0x90, 0x38, 0x68, 0x88, 0xC7, 0xA2,
0x7B, 0x9D, 0x3C, 0x6A, 0xE3, 0x56, 0xE9, 0x8F, 0x73, 0x3A, 0xA6, 0xFB,
0x3C, 0x43, 0x45, 0x01, 0xD4, 0xF8, 0x74, 0xAF, 0x97, 0xFD, 0xBF, 0xF1,
0xFE, 0xFF, 0xED, 0xE7, 0x9F, 0x8F, 0x3D, 0xF5, 0x95, 0x37, 0xD5, 0xD2,
0x48, 0x16, 0xAB, 0x73, 0x75, 0x13, 0x0E, 0x15, 0x41, 0x9A, 0x78, 0xAA,
0x69, 0x1F, 0xDE, 0x9B, 0x4C, 0x33, 0x63, 0x82, 0x55, 0x2F, 0xCC, 0xFB,
0xCE, 0x83, 0x54, 0x7C, 0xE6, 0x3C, 0x48, 0xFD, 0x0D, 0x1F, 0x7A, 0xBE,
0x69, 0x6F, 0x3F, 0x7A, 0x79, 0x0D, 0xBC, 0xFB, 0xD7, 0xC8, 0x7E, 0xF1,
0xDE, 0x2D, 0xE2, 0x80, 0x59, 0x9F, 0x58, 0xC8, 0x29, 0xCD, 0x11, 0x5E,
0xCD, 0x75, 0x18, 0xEC, 0x0E, 0x60, 0xDE, 0x64, 0xE5, 0x1A, 0xF8, 0x1F,
0x24, 0xB7, 0x37, 0xC5, 0x66, 0x04, 0xC1, 0x15, 0x41, 0xF1, 0x4B, 0xD6,
0x41, 0x87, 0x56, 0xC2, 0x40, 0xE1, 0xA2, 0x23, 0x1E, 0x89, 0xD8, 0x3B,
0x00, 0x6B, 0x1B, 0xED, 0x80, 0x8B, 0x8E, 0x4A, 0x30, 0x78, 0x0D, 0xAE,
0x19, 0x60, 0x33, 0x3A, 0x38,
};
const std::uint8_t MP3_MONO[] = {
0xFF, 0xFB, 0x14, 0xC4, 0x00, 0x00, 0x03, 0xB0, 0x21, 0x5E, 0xF4, 0x30, 0x80, 0x30, 0x98, 0x88, 0xA9, 0x83, 0x34, 0x70, 0x00, 0x18, 0x89, 0xCB,
0x20, 0x00, 0x3B, 0xBB, 0xB9, 0x9F, 0xD7, 0x0E, 0x06, 0x06, 0x06, 0x2C, 0x3E, 0xEF, 0x83, 0xE7, 0xF1, 0x00, 0x63, 0x83, 0xFD, 0x4E, 0xFC, 0xFF,
0x29, 0xE1, 0xF7, 0xD9, 0x87, 0x7E, 0xFF, 0x65, 0x9E, 0x21, 0xAF, 0x46, 0x58, 0xBB, 0x46, 0x58, 0xBA, 0x64, 0x40, 0x21, 0xB2, 0x6C, 0xFA, 0x6C,
0xF8, 0x42, 0x0E, 0x7C, 0x1E, 0x8F, 0x0D, 0xBF, 0x1B, 0x02, 0xBC, 0x24, 0x0D, 0x37, 0xCA, 0x9D, 0x52, 0xFD, 0x77, 0xE0, 0x16, 0xBA, 0x02, 0x04,
0xFF, 0xFB, 0x14, 0xC4, 0x03, 0x83, 0xC4, 0xE0, 0x2B, 0x28, 0x1D, 0xE4, 0x80, 0x20, 0x5D, 0x95, 0x60, 0x41, 0x70, 0x16, 0xC8, 0xD3, 0x02, 0x00,
0x2F, 0x12, 0x02, 0xD0, 0x40, 0x1D, 0x98, 0x4D, 0x06, 0x99, 0x84, 0xF2, 0x68, 0x98, 0xBF, 0x86, 0xD1, 0x84, 0xC8, 0x18, 0x2A, 0xA9, 0x79, 0x50,
0x85, 0xDE, 0x14, 0x88, 0x9A, 0xF8, 0x44, 0x02, 0xB0, 0x60, 0x62, 0x5E, 0x11, 0xE9, 0xDC, 0x18, 0x65, 0x8F, 0xFF, 0x7F, 0xFC, 0xB3, 0xF8, 0x58,
0xEF, 0xFF, 0xFF, 0xE1, 0x95, 0xF8, 0x44, 0x02, 0xB0, 0x60, 0x62, 0x5E, 0x11, 0xE9, 0xDC, 0x18, 0x65, 0x8F, 0xFF, 0x7F, 0xFC, 0xB3, 0xF8, 0x58,
0xFF, 0xFB, 0x14, 0xC4, 0x09, 0x83, 0xC2, 0xEC, 0xAB, 0x02, 0x0B, 0x80, 0xB6, 0x40, 0x5D, 0x95, 0x60, 0x41, 0x70, 0x16, 0xC8, 0xEF, 0xFF, 0xFF,
0xE1, 0x9F, 0x08, 0x80, 0x56, 0x0C, 0x0C, 0x4B, 0xC2, 0x3D, 0x3B, 0x83, 0x0C, 0xB1, 0xFF, 0xEF, 0xFF, 0x96, 0x7F, 0x0B, 0x1D, 0xFF, 0xFF, 0xFC,
0x31, 0xF8, 0x44, 0x02, 0xB0, 0x60, 0x62, 0x5E, 0x11, 0xE9, 0xDC, 0x18, 0x65, 0x8F, 0xFF, 0x7F, 0xFC, 0xB3, 0xF8, 0x58, 0xEF, 0xFF, 0xFF, 0xE1,
0x9F, 0x08, 0x80, 0x56, 0x0C, 0x0C, 0x4B, 0xC2, 0x3D, 0x3B, 0x83, 0x0C, 0xB1, 0xFF, 0xEF, 0xFF, 0x96, 0x7F, 0x0B, 0x1D, 0xFF, 0xFF, 0xFC, 0x31,
0xFF, 0xFB, 0x14, 0xC4, 0x17, 0x83, 0xC2, 0xEC, 0xAB, 0x02, 0x0B, 0x80, 0xB6, 0x40, 0x5D, 0x95, 0x60, 0x41, 0x70, 0x16, 0xC8, 0x96, 0x55, 0x8D,
0xBF, 0xE9, 0xD8, 0x50, 0x01, 0xA6, 0x17, 0x80, 0x34, 0x61, 0x00, 0x17, 0xC6, 0x15, 0x40, 0xD4, 0x61, 0x56, 0x25, 0x66, 0x3E, 0xA4, 0x92, 0x62,
0xC3, 0xED, 0x26, 0x23, 0xA5, 0x5C, 0x63, 0x10, 0x01, 0xC6, 0x0F, 0x20, 0x9E, 0x60, 0x62, 0x08, 0x26, 0x06, 0xE0, 0x12, 0xD6, 0x22, 0x02, 0x6C,
0x93, 0xC7, 0x04, 0x3E, 0xBF, 0xFE, 0xBF, 0xFF, 0x72, 0x62, 0x28, 0x22, 0xD1, 0x2F, 0xEF, 0xFD, 0xF1, 0x15, 0x09, 0x83, 0x08, 0x8C, 0x00, 0xFE,
0xFF, 0xFB, 0x14, 0xC4, 0x25, 0x80, 0x07, 0x74, 0x2D, 0x16, 0x15, 0xE7, 0x80, 0x00, 0xF2, 0x0C, 0xE8, 0x83, 0x36, 0xB0, 0x00, 0xC4, 0x42, 0x82,
0xC0, 0x86, 0x24, 0x2A, 0x02, 0x11, 0xFF, 0x02, 0x70, 0xF6, 0x07, 0x80, 0x9B, 0xCB, 0xCD, 0x0D, 0x00, 0x7C, 0x49, 0x1D, 0xBF, 0xD3, 0xDE, 0x3B,
0x52, 0x36, 0xFE, 0xFA, 0xF3, 0x66, 0xB5, 0x13, 0xDF, 0x06, 0x84, 0xA1, 0x2F, 0xCB, 0x05, 0x41, 0x5F, 0xF5, 0x2A, 0x4C, 0x41, 0x4D, 0x45, 0x34,
0x2E, 0x30, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0xFF, 0xFB, 0x14, 0xC4, 0x0E, 0x83, 0xC0, 0x00, 0x01, 0xA4, 0x1C, 0x00, 0x00, 0x20, 0x00, 0x00, 0x34, 0x80, 0x00, 0x00, 0x04, 0xAA, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
};
const std::uint8_t HEAAC_V2_MONO[] = {
0xFF, 0xF1, 0x58, 0x40, 0x10, 0x02, 0x80, 0x01, 0x40, 0x22, 0x80, 0xA3, 0x6E, 0xEF, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0x80,
0x00, 0x06, 0xF5, 0x61, 0x0A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5E, 0xFF, 0xF1, 0x58, 0x40, 0x10, 0x02, 0x80, 0x01, 0x40, 0x42, 0x80, 0xA3, 0x78, 0x46, 0x81, 0x00,
0x00, 0x00, 0x00, 0x00, 0x38, 0x76, 0xE4, 0x89, 0xB5, 0x65, 0xE5, 0xDF, 0xFE, 0xB7, 0x32, 0x7C, 0x7F, 0xF0, 0x00, 0x06, 0xF4, 0xC1, 0x0A, 0x5A,
0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A,
0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A, 0x5E, 0xFF, 0xF1, 0x58, 0x40, 0x18, 0xA2, 0x38, 0x01,
0x0A, 0x97, 0x98, 0xD8, 0x73, 0x75, 0x18, 0xBB, 0x6D, 0xCD, 0xA6, 0xE8, 0x7F, 0x09, 0xD5, 0xA0, 0x7E, 0x99, 0xC7, 0x42, 0xF2, 0x57, 0xBB, 0xC8,
0xAB, 0x51, 0x57, 0x0A, 0xBF, 0x56, 0x8A, 0x40, 0x48, 0xFB, 0xCC, 0xF1, 0xFF, 0x4E, 0x4C, 0x21, 0xEE, 0x7F, 0x10, 0xFD, 0xA6, 0xB4, 0xE2, 0xCC,
0x52, 0xA9, 0x38, 0x00, 0x00, 0xC4, 0x1A, 0x9A, 0xD2, 0x05, 0xE8, 0x94, 0xDB, 0xA5, 0x47, 0xFE, 0x92, 0xFC, 0x12, 0x41, 0x11, 0x08, 0x01, 0x22,
0x65, 0x54, 0x28, 0x24, 0x16, 0x72, 0xE9, 0xAA, 0xC7, 0x45, 0x33, 0xEC, 0x74, 0x13, 0xAC, 0x84, 0xD5, 0xD4, 0x95, 0xCB, 0x41, 0x9B, 0x55, 0x2D,
0xD5, 0xAC, 0x5C, 0xEF, 0xD4, 0x75, 0xF8, 0xD5, 0xCE, 0xC9, 0x64, 0xD9, 0xF5, 0x80, 0xD3, 0xD9, 0xAA, 0x5F, 0x1E, 0x45, 0x4F, 0xEA, 0x5F, 0xF8,
0xBF, 0x48, 0x1F, 0xAD, 0xDF, 0x0C, 0xE5, 0xF1, 0x7F, 0x65, 0xC0, 0x12, 0xFA, 0xBF, 0xE6, 0x40, 0x0D, 0xAA, 0xFD, 0x40, 0x02, 0x58, 0x64, 0xA4,
0x03, 0x2A, 0xC1, 0xAA, 0x79, 0x01, 0x6D, 0x37, 0x60, 0x78, 0x7B, 0x2B, 0x1B, 0x62, 0x6C, 0x87, 0xA7, 0xA2, 0xDB, 0x65, 0x00, 0xDE, 0x0F, 0xA0,
0x50, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDB, 0x92, 0x26, 0xD5, 0x97, 0x97, 0x7F, 0xFA, 0xDC, 0xC9, 0xF1, 0xFF, 0xC0, 0x01, 0xC0, 0xFF, 0xF1, 0x58,
0x40, 0x15, 0x02, 0x10, 0x01, 0x3C, 0xF3, 0x08, 0xB6, 0xA1, 0x99, 0x0C, 0x42, 0x0A, 0xA1, 0x40, 0xF6, 0x05, 0x0A, 0x6C, 0x0B, 0xC0, 0x1F, 0x1F,
0x19, 0x9D, 0x15, 0x2A, 0x56, 0x97, 0x6C, 0x63, 0x88, 0xF4, 0x89, 0x13, 0x53, 0xA1, 0x9D, 0x8E, 0x9A, 0x93, 0x0C, 0x6A, 0x18, 0x0F, 0x2C, 0xCB,
0x53, 0xB3, 0x93, 0xA9, 0xA9, 0x32, 0x63, 0xC3, 0x0C, 0x07, 0xF0, 0xF1, 0x3C, 0x98, 0xB9, 0x6B, 0x75, 0xB0, 0x95, 0xAD, 0x62, 0xDC, 0xA4, 0xB4,
0x75, 0xE1, 0xAD, 0xE9, 0x64, 0x31, 0x51, 0x24, 0xAE, 0x6E, 0x20, 0xC0, 0x9D, 0x70, 0x25, 0x47, 0x1D, 0x67, 0x4D, 0x5C, 0xE1, 0xDA, 0x4E, 0x8A,
0x9E, 0xF9, 0xFA, 0x62, 0x16, 0xDA, 0x99, 0x9F, 0xD0, 0xDC, 0x7D, 0xBD, 0x5F, 0x31, 0x8B, 0xC2, 0xE8, 0xD0, 0xB8, 0xE5, 0xC6, 0xC0, 0x37, 0x8F,
0x68, 0xBC, 0x92, 0x4C, 0xD0, 0x00, 0x01, 0xFC, 0xFD, 0x43, 0xF2, 0xF5, 0xFF, 0x9F, 0xBF, 0xAD, 0x6D, 0x56, 0x0D, 0x3F, 0xF4, 0xA5, 0xD9, 0x17,
0xFF, 0x20, 0x02, 0x7C, 0x02, 0xCC, 0x8B, 0x26, 0x49, 0xFF, 0xFB, 0x9E, 0xA2, 0x00, 0x0F, 0xE4, 0xDF, 0xF0, 0x00, 0x00, 0x70,
};
const std::uint8_t HEAAC_STEREO[] = {
0xFF, 0xF1, 0x58, 0x80, 0x10, 0x02, 0xC0, 0x21, 0x21, 0x45, 0x00, 0x14, 0x50, 0x01, 0x46, 0xAD, 0xD5, 0x81, 0x75, 0x00, 0x00, 0x00, 0x1C, 0x60,
0x18, 0x0D, 0xEA, 0xC2, 0x14, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4,
0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xBC, 0xFF, 0xF1, 0x58, 0x80, 0x1B, 0x62, 0x90, 0x21, 0x4A, 0xCC, 0x80, 0x1F, 0xEA, 0xFE, 0xBF, 0xC8,
0x87, 0x77, 0x07, 0x5B, 0x6B, 0x0A, 0xDA, 0x70, 0x6A, 0xC6, 0x8F, 0xE1, 0xE6, 0xC4, 0x36, 0x01, 0x48, 0xB1, 0x94, 0xF0, 0x67, 0x71, 0x13, 0x21,
0x28, 0xB0, 0x74, 0xC1, 0x02, 0x0B, 0xED, 0x1B, 0x75, 0xF2, 0x1D, 0x89, 0x8A, 0xFA, 0xCB, 0x17, 0x0D, 0x51, 0xAE, 0x81, 0x2D, 0xB3, 0x27, 0x07,
0x00, 0x69, 0x11, 0x1E, 0x51, 0x2E, 0x56, 0x4C, 0xD1, 0x9C, 0x39, 0x65, 0xED, 0x43, 0x53, 0x4E, 0x4E, 0x22, 0x8D, 0x5D, 0x48, 0x56, 0x50, 0x66,
0x75, 0x4B, 0x3D, 0x6B, 0x10, 0xE5, 0x38, 0x97, 0x8D, 0x5C, 0xEC, 0xCC, 0x6F, 0xDA, 0x1D, 0xD5, 0x99, 0x0C, 0xBD, 0x50, 0xDB, 0x92, 0xDE, 0x06,
0xD1, 0x0A, 0xE2, 0xD5, 0x32, 0x9C, 0xEA, 0x82, 0x1A, 0x30, 0x72, 0x92, 0xC1, 0x30, 0x88, 0xAC, 0x38, 0x15, 0xD9, 0xE7, 0x22, 0x5A, 0x97, 0x94,
0x0D, 0xE4, 0xFF, 0xFF, 0xFC, 0xC8, 0xD0, 0xEE, 0xDB, 0x60, 0x26, 0x6D, 0x11, 0x0D, 0x69, 0x10, 0x61, 0x63, 0xA7, 0xE7, 0xB7, 0x58, 0x11, 0x63,
0x29, 0xE0, 0xFB, 0xBD, 0x8E, 0x3C, 0x98, 0xBC, 0x01, 0x7E, 0x8F, 0x7B, 0xF7, 0xCB, 0x3A, 0xC2, 0xC0, 0xC2, 0xC2, 0xCB, 0x01, 0x1F, 0xA3, 0x94,
0xE8, 0x28, 0x44, 0x40, 0x52, 0x10, 0x42, 0x48, 0x0A, 0x94, 0x53, 0x9D, 0x57, 0xB0, 0x4B, 0x3E, 0x50, 0x80, 0xDF, 0xD2, 0x70, 0x30, 0x95, 0x33,
0x92, 0x2C, 0xAD, 0x9D, 0x59, 0x74, 0x83, 0xC0, 0x00, 0x00, 0x38, 0xFF, 0xF1, 0x58, 0x80, 0x16, 0xC2, 0x74, 0x21, 0x79, 0x08, 0x00, 0x87, 0xFF,
0xFF, 0xCF, 0x11, 0x6C, 0xCC, 0x21, 0x92, 0x14, 0x02, 0x80, 0xE8, 0x05, 0x50, 0x10, 0x50, 0x3F, 0xC7, 0xC6, 0x67, 0x50, 0xB0, 0xBB, 0x63, 0x1A,
0x77, 0x48, 0xF3, 0x0E, 0x0A, 0x02, 0x2F, 0xC6, 0xDA, 0xD2, 0xFA, 0xDA, 0x2D, 0x32, 0x15, 0x6E, 0xEE, 0xF0, 0x11, 0x7F, 0x0F, 0x13, 0xC9, 0x48,
0xEB, 0x84, 0x2D, 0x63, 0xAD, 0xAD, 0x61, 0xCA, 0x43, 0x5E, 0x1A, 0xDC, 0x31, 0x76, 0x4B, 0x9C, 0xBB, 0xD1, 0xF7, 0xD4, 0x84, 0xF0, 0x35, 0x83,
0x78, 0xEE, 0x95, 0x05, 0x2E, 0x61, 0x76, 0xDB, 0xE1, 0x68, 0xC9, 0x23, 0xA4, 0x1E, 0xAA, 0x71, 0xCA, 0x9A, 0xA5, 0xEE, 0x88, 0x0D, 0x0F, 0xE7,
0xFE, 0x55, 0x6D, 0x0F, 0x61, 0xA3, 0xAE, 0xEE, 0xF3, 0x08, 0xCB, 0x13, 0x08, 0x28, 0x0A, 0x1E, 0x28, 0x40, 0x70, 0xA0, 0xA7, 0x84, 0x14, 0x15,
0xF5, 0xD0, 0x50, 0x53, 0x51, 0x5F, 0x32, 0x89, 0xA8, 0xAC, 0x1F, 0x73, 0x62, 0xD1, 0x67, 0x53, 0x57, 0x86, 0x2C, 0x80, 0x44, 0xFB, 0xC2, 0xF4,
0xAF, 0x24, 0x93, 0x1D, 0x40, 0x00, 0xFF, 0x89, 0x36, 0xFF, 0xC6, 0x45, 0x23, 0x7F, 0xF0, 0x5B, 0xCC, 0x00, 0x00, 0x00, 0x03, 0x20, 0x0C, 0x01,
0x38,
};
constexpr std::int32_t errorApiFail = static_cast<std::int32_t>(0x807F0000);
constexpr std::int32_t errorInvalidType = static_cast<std::int32_t>(0x807F0001);
constexpr std::int32_t errorArg = static_cast<std::int32_t>(0x807F0002);
constexpr std::int32_t errorInvalidParamSize = static_cast<std::int32_t>(0x807F0004);
constexpr std::int32_t errorInvalidBsiInfoSize = static_cast<std::int32_t>(0x807F0005);
constexpr std::int32_t errorInvalidCtrlPointer = static_cast<std::int32_t>(0x807F0008);
constexpr std::int32_t errorInvalidAuInfoPointer = static_cast<std::int32_t>(0x807F000B);
constexpr std::int32_t errorInvalidHandle = static_cast<std::int32_t>(0x807F000F);
constexpr std::int32_t errorInvalidWordLength = static_cast<std::int32_t>(0x807F0010);
constexpr std::int32_t errorInvalidAuSize = static_cast<std::int32_t>(0x807F0011);
constexpr std::int32_t errorInvalidPcmSize = static_cast<std::int32_t>(0x807F0012);
constexpr std::int32_t errorInvalidConfigNumber = static_cast<std::int32_t>(0x807F0303);
constexpr std::int32_t errorInvalidAt9Config = static_cast<std::int32_t>(0x807F1000);
struct Streams {
AudiodecAuInfo au{sizeof(AudiodecAuInfo), nullptr, 0};
AudiodecPcmItem pcm{sizeof(AudiodecPcmItem), nullptr, 0};
std::vector<std::uint8_t> output = std::vector<std::uint8_t>(16384);
};
std::int32_t Decode(std::int32_t handle, AudiodecCtrl& ctrl, Streams& streams, const std::uint8_t* data, std::size_t size, std::uint32_t room = 16384) {
streams.au.p_au_addr = const_cast<std::uint8_t*>(data);
streams.au.ui_au_size = static_cast<std::uint32_t>(size);
streams.pcm.p_pcm_addr = streams.output.data();
streams.pcm.ui_pcm_size = room;
ctrl.pAuInfo = &streams.au;
ctrl.pPcmItem = &streams.pcm;
return sceAudiodecDecode(handle, &ctrl);
}
int ZeroCrossings(const std::int16_t* samples, std::size_t count, std::size_t stride) {
int crossings = 0;
for (std::size_t i = stride; i < count * stride; i += stride) crossings += (samples[i - stride] < 0) != (samples[i] < 0);
return crossings;
}
std::size_t AdtsLength(const std::uint8_t* frame) {
return static_cast<std::size_t>((frame[3] & 3) << 11 | frame[4] << 3 | frame[5] >> 5);
}
void TestAac(bool adts, std::uint32_t maxChannels = 2) {
AudiodecParamM4aac param{sizeof(param), 1, adts ? 1u : 2u, 3, maxChannels, 0};
AudiodecM4aacInfo info{sizeof(info), 0, 0, 0, 0};
AudiodecCtrl ctrl{&param, &info, nullptr, nullptr};
const std::int32_t handle = sceAudiodecCreateDecoder(&ctrl, 3);
Require(handle > 0 && info.ui_sampling_freq == 48000 && info.ui_number_of_channels == maxChannels);
Streams streams;
int crossings = 0;
for (std::size_t offset = 0, frame = 0; offset < sizeof(AAC_ADTS); offset += AdtsLength(AAC_ADTS + offset), ++frame) {
const std::size_t length = AdtsLength(AAC_ADTS + offset);
const std::uint8_t* data = adts ? AAC_ADTS + offset : AAC_ADTS + offset + 7;
const std::size_t size = adts ? sizeof(AAC_ADTS) - offset : length - 7;
Require(Decode(handle, ctrl, streams, data, size) == 0);
Require(streams.au.ui_au_size == (adts ? length : length - 7));
Require(streams.pcm.ui_pcm_size == 1024 * 2 * 2 && info.i_result == 0);
Require(info.ui_sampling_freq == 48000 && info.ui_number_of_channels == 2 && info.ui_heaac == 0);
if (frame == 2) crossings = ZeroCrossings(reinterpret_cast<const std::int16_t*>(streams.output.data()), 1024, 2);
}
Require(crossings >= 38 && crossings <= 46);
Require(Decode(handle, ctrl, streams, AAC_ADTS, sizeof(AAC_ADTS), 1024) == errorInvalidPcmSize);
if (adts) {
Require(Decode(handle, ctrl, streams, AAC_ADTS, 50) == errorApiFail && info.i_result == -5);
Require(Decode(handle, ctrl, streams, AAC_ADTS + 1, 50) == errorApiFail && info.i_result == -4);
}
Require(sceAudiodecClearContext(handle) == 0);
Require(sceAudiodecDeleteDecoder(handle) == 0);
}
void TestAacRaw51(std::uint32_t maxChannels) {
AudiodecParamM4aac param{sizeof(param), 1, 2, 3, maxChannels, 0};
AudiodecM4aacInfo info{sizeof(info), 0, 0, 0, 0};
AudiodecCtrl ctrl{&param, &info, nullptr, nullptr};
const std::int32_t handle = sceAudiodecCreateDecoder(&ctrl, 3);
Require(handle > 0 && info.ui_number_of_channels == maxChannels);
Streams streams;
Require(Decode(handle, ctrl, streams, AAC_RAW_51, sizeof(AAC_RAW_51)) == 0);
Require(streams.pcm.ui_pcm_size == 1024 * 6 * 2);
Require(info.ui_sampling_freq == 48000 && info.ui_number_of_channels == 6 && info.i_result == 0);
Require(sceAudiodecClearContext(handle) == 0);
Require(sceAudiodecDeleteDecoder(handle) == 0);
}
double UpperHalfEnergyShare(const std::int16_t* samples, std::size_t count, std::size_t stride) {
double upper = 0;
double total = 0;
for (std::size_t bin = 1; bin < count / 2; ++bin) {
double real = 0;
double imaginary = 0;
for (std::size_t i = 0; i < count; ++i) {
const double phase = 2 * std::numbers::pi * static_cast<double>(bin * i % count) / static_cast<double>(count);
real += samples[i * stride] * std::cos(phase);
imaginary += samples[i * stride] * std::sin(phase);
}
total += real * real + imaginary * imaginary;
if (bin >= count / 4) upper += real * real + imaginary * imaginary;
}
return upper / total;
}
void TestHeAac(const std::uint8_t* stream, std::size_t streamSize, std::uint32_t channels, bool adts, bool highEfficiency) {
AudiodecParamM4aac param{sizeof(param), 1, adts ? 1u : 2u, 6, channels, highEfficiency ? 1u : 0u};
AudiodecM4aacInfo info{sizeof(info), 0, 0, 0, 0};
AudiodecCtrl ctrl{&param, &info, nullptr, nullptr};
const std::int32_t handle = sceAudiodecCreateDecoder(&ctrl, 3);
Require(handle > 0);
Streams streams;
const std::uint32_t samples = highEfficiency ? 2048 : 1024;
const std::uint32_t room = samples * channels * 2;
for (std::size_t offset = 0; offset < streamSize; offset += AdtsLength(stream + offset)) {
const std::size_t length = AdtsLength(stream + offset);
Require(Decode(handle, ctrl, streams, adts ? stream + offset : stream + offset + 7, adts ? length : length - 7, room) == 0);
Require(streams.au.ui_au_size == (adts ? length : length - 7));
Require(streams.pcm.ui_pcm_size == room && info.i_result == 0);
Require(info.ui_sampling_freq == (highEfficiency ? 48000u : 24000u) && info.ui_number_of_channels == channels);
}
if (highEfficiency) {
Require(info.ui_heaac == 1);
Require(UpperHalfEnergyShare(reinterpret_cast<const std::int16_t*>(streams.output.data()), samples, channels) > 0.02);
}
Require(sceAudiodecDeleteDecoder(handle) == 0);
}
void TestMp3() {
AudiodecParamMp3 param{sizeof(param), 2};
AudiodecMp3Info info{};
info.ui_size = sizeof(info);
AudiodecCtrl ctrl{&param, &info, nullptr, nullptr};
const std::int32_t handle = sceAudiodecCreateDecoder(&ctrl, 2);
Require(handle > 0);
Streams streams;
std::size_t offset = 0;
int frames = 0;
float peak = 0;
while (offset < sizeof(MP3_MONO)) {
Require(Decode(handle, ctrl, streams, MP3_MONO + offset, sizeof(MP3_MONO) - offset) == 0);
Require(streams.au.ui_au_size == 144 * 32000 / 48000 + (MP3_MONO[offset + 2] >> 1 & 1));
Require(streams.pcm.ui_pcm_size == 1152 * 4);
Require(info.ui_header >> 21 == 0x7FF && info.uc_mode == 3 && info.i_result == 0);
for (std::size_t i = 0; i < 1152; ++i) peak = std::fmax(peak, std::fabs(reinterpret_cast<const float*>(streams.output.data())[i]));
offset += streams.au.ui_au_size;
++frames;
}
Require(offset == sizeof(MP3_MONO) && frames == 6 && peak > 0.1f && peak < 0.15f);
Require(Decode(handle, ctrl, streams, MP3_MONO, 10) == errorApiFail);
Require(Decode(handle, ctrl, streams, MP3_MONO + 1, 100) == errorApiFail);
Require(sceAudiodecDeleteDecoder(handle) == 0);
}
void TestAt9() {
AudiodecParamAt9 param{sizeof(param), 1, {0xFE, 0x72, 0x1F, 0xF0}};
AudiodecAt9Info info{};
info.ui_size = sizeof(info);
AudiodecCtrl ctrl{&param, &info, nullptr, nullptr};
const std::int32_t handle = sceAudiodecCreateDecoder(&ctrl, 1);
Require(handle > 0);
Require(info.ui_channel == 2 && info.ui_sampling_rate == 48000 && info.ui_frame_samples == 256);
Require(info.ui_super_frame_size == 1024 && info.ui_frames_in_super_frame == 4 && info.ui_bitrate == 384000);
Streams streams;
const std::vector<std::uint8_t> silence(1024);
Require(Decode(handle, ctrl, streams, silence.data(), 1023) == errorApiFail);
Require(Decode(handle, ctrl, streams, silence.data(), silence.size(), 4095) == errorInvalidPcmSize);
Require(Decode(handle, ctrl, streams, silence.data(), silence.size()) == errorApiFail);
Require(sceAudiodecDeleteDecoder(handle) == 0);
param.ui_config_data[0] = 0xFD;
Require(sceAudiodecCreateDecoder(&ctrl, 1) == errorInvalidAt9Config);
}
}
int main() {
Require(sceAudiodecInitLibrary(4) == errorInvalidType);
Require(sceAudiodecTermLibrary(0) == errorInvalidType);
AudiodecParamMp3 mp3{sizeof(mp3), 1};
AudiodecMp3Info mp3Info{};
mp3Info.ui_size = sizeof(mp3Info);
AudiodecCtrl ctrl{&mp3, &mp3Info, nullptr, nullptr};
Require(sceAudiodecCreateDecoder(&ctrl, 2) == errorArg);
for (std::uint32_t type = 1; type <= 3; ++type) Require(sceAudiodecInitLibrary(type) == 0);
Require(sceAudiodecCreateDecoder(nullptr, 2) == errorInvalidCtrlPointer);
Require(sceAudiodecCreateDecoder(&ctrl, 5) == errorInvalidType);
mp3.ui_size = 12;
Require(sceAudiodecCreateDecoder(&ctrl, 2) == errorInvalidParamSize);
mp3.ui_size = sizeof(mp3);
mp3Info.ui_size = 16;
Require(sceAudiodecCreateDecoder(&ctrl, 2) == errorInvalidBsiInfoSize);
mp3Info.ui_size = sizeof(mp3Info);
mp3.i_bw_pcm = 3;
Require(sceAudiodecCreateDecoder(&ctrl, 2) == errorInvalidWordLength);
mp3.i_bw_pcm = 1;
AudiodecParamM4aac aac{sizeof(aac), 1, 3, 3, 2, 0};
AudiodecM4aacInfo aacInfo{sizeof(aacInfo), 0, 0, 0, 0};
AudiodecCtrl aacCtrl{&aac, &aacInfo, nullptr, nullptr};
Require(sceAudiodecCreateDecoder(&aacCtrl, 3) == errorInvalidConfigNumber);
const std::int32_t handle = sceAudiodecCreateDecoder(&ctrl, 2);
Require(handle > 0);
Streams streams;
Require(sceAudiodecDecode(handle, &ctrl) == errorInvalidAuInfoPointer);
Require(Decode(handle, ctrl, streams, MP3_MONO, 0) == errorInvalidAuSize);
Require(Decode(handle, ctrl, streams, MP3_MONO, sizeof(MP3_MONO), 0) == errorInvalidPcmSize);
Require(Decode(handle + 1, ctrl, streams, MP3_MONO, sizeof(MP3_MONO)) == errorInvalidHandle);
Require(sceAudiodecDeleteDecoder(handle) == 0);
Require(sceAudiodecDeleteDecoder(handle) == errorInvalidHandle);
Require(sceAudiodecClearContext(handle) == errorInvalidHandle);
TestAac(true);
TestAac(false);
TestAac(false, 6);
TestAac(false, 8);
TestAacRaw51(6);
TestAacRaw51(8);
for (const bool adts : {true, false}) {
for (const bool highEfficiency : {true, false}) {
TestHeAac(HEAAC_V2_MONO, sizeof(HEAAC_V2_MONO), 1, adts, highEfficiency);
TestHeAac(HEAAC_STEREO, sizeof(HEAAC_STEREO), 2, adts, highEfficiency);
}
}
TestMp3();
TestAt9();
for (std::uint32_t type = 1; type <= 3; ++type) Require(sceAudiodecTermLibrary(type) == 0);
}