Add pre-packaged dependency libraries (ESP32-audioI2S and PNGdec)
BIN
libraries/ESP32-audioI2S/additional_info/Arduino Library.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/Audio Duration.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/Breadboard.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
libraries/ESP32-audioI2S/additional_info/DAC CS4344.jpg
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/DAC PCM5102A.jpg
Normal file
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 309 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/ESP32_I2S_PCM5102A.JPG
Normal file
|
After Width: | Height: | Size: 107 KiB |
|
After Width: | Height: | Size: 84 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/ESP32_I2S_UDA1334A.JPG
Normal file
|
After Width: | Height: | Size: 337 KiB |
|
After Width: | Height: | Size: 177 KiB |
|
After Width: | Height: | Size: 183 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/Impulsdiagramm.jpg
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/M4A Coverart Block.jpg
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/Ogg_Metadatapicture.png
Normal file
|
After Width: | Height: | Size: 381 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/Partition Scheme.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/Testfiles/Collide.ogg
Normal file
@@ -0,0 +1,5 @@
|
||||
#EXTM3U
|
||||
#EXTINF:18,Bjarne Liller - Olsen Banden (Titelmusik der Olsenbande) - Olsen-Banden.mp3
|
||||
https://raw.githubusercontent.com/schreibfaul1/ESP32-audioI2S/master/additional_info/Testfiles/Olsen-Banden.mp3
|
||||
#EXTINF:10,Santiano-Wellermann - Santiano-Wellerman.flac
|
||||
https://raw.githubusercontent.com/schreibfaul1/ESP32-audioI2S/master/additional_info/Testfiles/Santiano-Wellerman.flac
|
||||
BIN
libraries/ESP32-audioI2S/additional_info/Testfiles/sample.opus
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/lowpass.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
libraries/ESP32-audioI2S/additional_info/minimal.JPG
Normal file
|
After Width: | Height: | Size: 36 KiB |
@@ -0,0 +1,589 @@
|
||||
// based on helix aac decoder
|
||||
#pragma once
|
||||
//#pragma GCC optimize ("O3")
|
||||
//#pragma GCC diagnostic ignored "-Wnarrowing"
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#define AAC_ENABLE_MPEG4
|
||||
|
||||
#if (defined CONFIG_IDF_TARGET_ESP32S3 && defined BOARD_HAS_PSRAM)
|
||||
#define AAC_ENABLE_SBR // needs additional 60KB DRAM,
|
||||
#endif
|
||||
|
||||
#define ASSERT(x) /* do nothing */
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) std::max(a,b)
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) std::min(a,b)
|
||||
#endif
|
||||
|
||||
|
||||
/* AAC file format */
|
||||
enum {
|
||||
AAC_FF_Unknown = 0, /* should be 0 on init */
|
||||
AAC_FF_ADTS = 1,
|
||||
AAC_FF_ADIF = 2,
|
||||
AAC_FF_RAW = 3
|
||||
};
|
||||
|
||||
/* syntactic element type */
|
||||
enum {
|
||||
AAC_ID_INVALID = -1,
|
||||
AAC_ID_SCE = 0,
|
||||
AAC_ID_CPE = 1,
|
||||
AAC_ID_CCE = 2,
|
||||
AAC_ID_LFE = 3,
|
||||
AAC_ID_DSE = 4,
|
||||
AAC_ID_PCE = 5,
|
||||
AAC_ID_FIL = 6,
|
||||
AAC_ID_END = 7
|
||||
};
|
||||
|
||||
enum {
|
||||
ERR_AAC_NONE = 0,
|
||||
ERR_AAC_INDATA_UNDERFLOW = -1,
|
||||
ERR_AAC_NULL_POINTER = -2,
|
||||
ERR_AAC_INVALID_ADTS_HEADER = -3,
|
||||
ERR_AAC_INVALID_ADIF_HEADER = -4,
|
||||
ERR_AAC_INVALID_FRAME = -5,
|
||||
ERR_AAC_MPEG4_UNSUPPORTED = -6,
|
||||
ERR_AAC_CHANNEL_MAP = -7,
|
||||
ERR_AAC_SYNTAX_ELEMENT = -8,
|
||||
ERR_AAC_DEQUANT = -9,
|
||||
ERR_AAC_STEREO_PROCESS = -10,
|
||||
ERR_AAC_PNS = -11,
|
||||
ERR_AAC_SHORT_BLOCK_DEINT = -12,
|
||||
ERR_AAC_TNS = -13,
|
||||
ERR_AAC_IMDCT = -14,
|
||||
ERR_AAC_NCHANS_TOO_HIGH = -15,
|
||||
ERR_AAC_SBR_INIT = -16,
|
||||
ERR_AAC_SBR_BITSTREAM = -17,
|
||||
ERR_AAC_SBR_DATA = -18,
|
||||
ERR_AAC_SBR_PCM_FORMAT = -19,
|
||||
ERR_AAC_SBR_NCHANS_TOO_HIGH = -20,
|
||||
ERR_AAC_SBR_SINGLERATE_UNSUPPORTED = -21,
|
||||
ERR_AAC_RAWBLOCK_PARAMS = -22,
|
||||
ERR_AAC_UNKNOWN = -9999
|
||||
};
|
||||
|
||||
enum {
|
||||
SBR_GRID_FIXFIX = 0,
|
||||
SBR_GRID_FIXVAR = 1,
|
||||
SBR_GRID_VARFIX = 2,
|
||||
SBR_GRID_VARVAR = 3
|
||||
};
|
||||
|
||||
enum {
|
||||
HuffTabSBR_tEnv15 = 0,
|
||||
HuffTabSBR_fEnv15 = 1,
|
||||
HuffTabSBR_tEnv15b = 2,
|
||||
HuffTabSBR_fEnv15b = 3,
|
||||
HuffTabSBR_tEnv30 = 4,
|
||||
HuffTabSBR_fEnv30 = 5,
|
||||
HuffTabSBR_tEnv30b = 6,
|
||||
HuffTabSBR_fEnv30b = 7,
|
||||
HuffTabSBR_tNoise30 = 8,
|
||||
HuffTabSBR_fNoise30 = 5,
|
||||
HuffTabSBR_tNoise30b = 9,
|
||||
HuffTabSBR_fNoise30b = 7
|
||||
};
|
||||
|
||||
typedef struct _AACDecInfo_t {
|
||||
/* raw decoded data, before rounding to 16-bit PCM (for postprocessing such as SBR) */
|
||||
void *rawSampleBuf[2];
|
||||
int32_t rawSampleBytes;
|
||||
int32_t rawSampleFBits;
|
||||
/* fill data (can be used for processing SBR or other extensions) */
|
||||
uint8_t *fillBuf;
|
||||
int32_t fillCount;
|
||||
int32_t fillExtType;
|
||||
int32_t prevBlockID; /* block information */
|
||||
int32_t currBlockID;
|
||||
int32_t currInstTag;
|
||||
int32_t sbDeinterleaveReqd[2]; // [MAX_NCHANS_ELEM]
|
||||
int32_t adtsBlocksLeft;
|
||||
int32_t bitRate; /* user-accessible info */
|
||||
int32_t nChans;
|
||||
int32_t sampRate;
|
||||
float compressionRatio;
|
||||
int32_t id; /* 0: MPEG-4, 1: MPEG2 */
|
||||
int32_t profile; /* 0: Main profile, 1: LowComplexity (LC), 2: ScalableSamplingRate (SSR), 3: reserved */
|
||||
int32_t format;
|
||||
int32_t sbrEnabled;
|
||||
int32_t tnsUsed;
|
||||
int32_t pnsUsed;
|
||||
int32_t frameCount;
|
||||
} AACDecInfo_t;
|
||||
|
||||
|
||||
typedef struct _aac_BitStreamInfo_t {
|
||||
uint8_t *bytePtr;
|
||||
uint32_t iCache;
|
||||
int32_t cachedBits;
|
||||
int32_t nBytes;
|
||||
} aac_BitStreamInfo_t;
|
||||
|
||||
typedef union _U64 {
|
||||
int64_t w64;
|
||||
struct {
|
||||
uint32_t lo32;
|
||||
int32_t hi32;
|
||||
} r;
|
||||
} U64;
|
||||
|
||||
typedef struct _AACFrameInfo_t {
|
||||
int32_t bitRate;
|
||||
int32_t nChans;
|
||||
int32_t sampRateCore;
|
||||
int32_t sampRateOut;
|
||||
int32_t bitsPerSample;
|
||||
int32_t outputSamps;
|
||||
int32_t profile;
|
||||
int32_t tnsUsed;
|
||||
int32_t pnsUsed;
|
||||
} AACFrameInfo_t;
|
||||
|
||||
typedef struct _HuffInfo_t {
|
||||
int32_t maxBits; /* number of bits in longest codeword */
|
||||
uint8_t count[20]; /* count[MAX_HUFF_BITS] = number of codes with length i+1 bits */
|
||||
int32_t offset; /* offset into symbol table */
|
||||
} HuffInfo_t;
|
||||
|
||||
typedef struct _PulseInfo_t {
|
||||
uint8_t pulseDataPresent;
|
||||
uint8_t numPulse;
|
||||
uint8_t startSFB;
|
||||
uint8_t offset[4]; // [MAX_PULSES]
|
||||
uint8_t amp[4]; // [MAX_PULSES]
|
||||
} PulseInfo_t;
|
||||
|
||||
typedef struct _TNSInfo_t {
|
||||
uint8_t tnsDataPresent;
|
||||
uint8_t numFilt[8]; // [MAX_TNS_FILTERS] max 1 filter each for 8 short windows, or 3 filters for 1 long window
|
||||
uint8_t coefRes[8]; // [MAX_TNS_FILTERS]
|
||||
uint8_t length[8]; // [MAX_TNS_FILTERS]
|
||||
uint8_t order[8]; // [MAX_TNS_FILTERS]
|
||||
uint8_t dir[8]; // [MAX_TNS_FILTERS]
|
||||
int8_t coef[60]; // [MAX_TNS_COEFS] max 3 filters * 20 coefs for 1 long window,
|
||||
// or 1 filter * 7 coefs for each of 8 short windows
|
||||
} TNSInfo_t;
|
||||
|
||||
typedef struct _GainControlInfo_t {
|
||||
uint8_t gainControlDataPresent;
|
||||
uint8_t maxBand;
|
||||
uint8_t adjNum[3][8]; // [MAX_GAIN_BANDS][MAX_GAIN_WIN]
|
||||
uint8_t alevCode[3][8][7]; // [MAX_GAIN_BANDS][MAX_GAIN_WIN][MAX_GAIN_ADJUST]
|
||||
uint8_t alocCode[3][8][7]; // [MAX_GAIN_BANDS][MAX_GAIN_WIN][MAX_GAIN_ADJUST]
|
||||
} GainControlInfo_t;
|
||||
|
||||
typedef struct _ICSInfo_t {
|
||||
uint8_t icsResBit;
|
||||
uint8_t winSequence;
|
||||
uint8_t winShape;
|
||||
uint8_t maxSFB;
|
||||
uint8_t sfGroup;
|
||||
uint8_t predictorDataPresent;
|
||||
uint8_t predictorReset;
|
||||
uint8_t predictorResetGroupNum;
|
||||
uint8_t predictionUsed[41]; // [MAX_PRED_SFB]
|
||||
uint8_t numWinGroup;
|
||||
uint8_t winGroupLen[8]; // [MAX_WIN_GROUPS]
|
||||
} ICSInfo_t;
|
||||
|
||||
typedef struct _ADTSHeader_t {
|
||||
/* fixed */
|
||||
uint8_t id; /* MPEG bit - should be 1 */
|
||||
uint8_t layer; /* MPEG layer - should be 0 */
|
||||
uint8_t protectBit; /* 0 = CRC word follows, 1 = no CRC word */
|
||||
uint8_t profile; /* 0 = main, 1 = LC, 2 = SSR, 3 = reserved */
|
||||
uint8_t sampRateIdx; /* sample rate index range = [0, 11] */
|
||||
uint8_t privateBit; /* ignore */
|
||||
uint8_t channelConfig; /* 0 = implicit, >0 = use default table */
|
||||
uint8_t origCopy; /* 0 = copy, 1 = original */
|
||||
uint8_t home; /* ignore */
|
||||
/* variable */
|
||||
uint8_t copyBit; /* 1 bit of the 72-bit copyright ID (transmitted as 1 bit per frame) */
|
||||
uint8_t copyStart; /* 1 = this bit starts the 72-bit ID, 0 = it does not */
|
||||
int32_t frameLength; /* length of frame */
|
||||
int32_t bufferFull; /* number of 32-bit words left in enc buffer, 0x7FF = VBR */
|
||||
uint8_t numRawDataBlocks; /* number of raw data blocks in frame */
|
||||
/* CRC */
|
||||
int32_t crcCheckWord; /* 16-bit CRC check word (present if protectBit == 0) */
|
||||
} ADTSHeader_t;
|
||||
|
||||
typedef struct _ADIFHeader_t {
|
||||
uint8_t copyBit; /* 0 = no copyright ID, 1 = 72-bit copyright ID follows immediately */
|
||||
uint8_t origCopy; /* 0 = copy, 1 = original */
|
||||
uint8_t home; /* ignore */
|
||||
uint8_t bsType; /* bitstream type: 0 = CBR, 1 = VBR */
|
||||
int32_t bitRate; /* bitRate: CBR = bits/sec, VBR = peak bits/frame, 0 = unknown */
|
||||
uint8_t numPCE; /* number of program config elements (max = 16) */
|
||||
int32_t bufferFull; /* bits left in bit reservoir */
|
||||
uint8_t copyID[9]; /* [ADIF_COPYID_SIZE] optional 72-bit copyright ID */
|
||||
} ADIFHeader_t;
|
||||
|
||||
/* sizeof(ProgConfigElement_t) = 82 bytes (if KEEP_PCE_COMMENTS not defined) */
|
||||
typedef struct _ProgConfigElement_t {
|
||||
uint8_t elemInstTag; /* element instance tag */
|
||||
uint8_t profile; /* 0 = main, 1 = LC, 2 = SSR, 3 = reserved */
|
||||
uint8_t sampRateIdx; /* sample rate index range = [0, 11] */
|
||||
uint8_t numFCE; /* number of front channel elements (max = 15) */
|
||||
uint8_t numSCE; /* number of side channel elements (max = 15) */
|
||||
uint8_t numBCE; /* number of back channel elements (max = 15) */
|
||||
uint8_t numLCE; /* number of LFE channel elements (max = 3) */
|
||||
uint8_t numADE; /* number of associated data elements (max = 7) */
|
||||
uint8_t numCCE; /* number of valid channel coupling elements (max = 15) */
|
||||
uint8_t monoMixdown; /* mono mixdown: bit 4 = present flag, bits 3-0 = element number */
|
||||
uint8_t stereoMixdown; /* stereo mixdown: bit 4 = present flag, bits 3-0 = element number */
|
||||
uint8_t matrixMixdown; /* bit 4 = present flag, bit 3 = unused,bits 2-1 = index, bit 0 = pseudo-surround enable */
|
||||
uint8_t fce[15]; /* [MAX_NUM_FCE] front element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
|
||||
uint8_t sce[15]; /* [MAX_NUM_SCE] side element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
|
||||
uint8_t bce[15]; /* [MAX_NUM_BCE] back element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
|
||||
uint8_t lce[3]; /* [MAX_NUM_LCE] instance tag for LFE elements */
|
||||
uint8_t ade[7]; /* [MAX_NUM_ADE] instance tag for ADE elements */
|
||||
uint8_t cce[15]; /* [MAX_NUM_BCE] channel coupling elements: bit 4 = switching flag, bits 3-0 = inst tag */
|
||||
} ProgConfigElement_t;
|
||||
|
||||
typedef struct _SBRHeader {
|
||||
int32_t count;
|
||||
|
||||
uint8_t ampRes;
|
||||
uint8_t startFreq;
|
||||
uint8_t stopFreq;
|
||||
uint8_t crossOverBand;
|
||||
uint8_t resBitsHdr;
|
||||
uint8_t hdrExtra1;
|
||||
uint8_t hdrExtra2;
|
||||
|
||||
uint8_t freqScale;
|
||||
uint8_t alterScale;
|
||||
uint8_t noiseBands;
|
||||
|
||||
uint8_t limiterBands;
|
||||
uint8_t limiterGains;
|
||||
uint8_t interpFreq;
|
||||
uint8_t smoothMode;
|
||||
} SBRHeader;
|
||||
|
||||
/* need one SBRGrid per channel, updated every frame */
|
||||
typedef struct _SBRGrid {
|
||||
uint8_t frameClass;
|
||||
uint8_t ampResFrame;
|
||||
uint8_t pointer;
|
||||
|
||||
uint8_t numEnv; /* L_E */
|
||||
uint8_t envTimeBorder[5 + 1]; // [MAX_NUM_ENV+1] /* t_E */
|
||||
uint8_t freqRes[5]; // [MAX_NUM_ENV]/* r */
|
||||
uint8_t numNoiseFloors; /* L_Q */
|
||||
uint8_t noiseTimeBorder[2 + 1]; // [MAX_NUM_NOISE_FLOORS+1] /* t_Q */
|
||||
|
||||
uint8_t numEnvPrev;
|
||||
uint8_t numNoiseFloorsPrev;
|
||||
uint8_t freqResPrev;
|
||||
} SBRGrid;
|
||||
|
||||
/* need one SBRFreq per element (SCE/CPE/LFE), updated only on header reset */
|
||||
typedef struct _SBRFreq {
|
||||
int32_t kStart; /* k_x */
|
||||
int32_t nMaster;
|
||||
int32_t nHigh;
|
||||
int32_t nLow;
|
||||
int32_t nLimiter; /* N_l */
|
||||
int32_t numQMFBands; /* M */
|
||||
int32_t numNoiseFloorBands; /* Nq */
|
||||
int32_t kStartPrev;
|
||||
int32_t numQMFBandsPrev;
|
||||
uint8_t freqMaster[48 + 1]; // [MAX_QMF_BANDS + 1] /* not necessary to save this after derived tables are generated */
|
||||
uint8_t freqHigh[48 + 1]; // [MAX_QMF_BANDS + 1]
|
||||
uint8_t freqLow[48 / 2 + 1]; // [MAX_QMF_BANDS / 2 + 1] /* nLow = nHigh - (nHigh >> 1) */
|
||||
uint8_t freqNoise[5 + 1]; // [MAX_NUM_NOISE_FLOOR_BANDS+1]
|
||||
uint8_t freqLimiter[48 / 2 + 5];// [MAX_QMF_BANDS / 2 + MAX_NUM_PATCHES] /* max (intermediate) size = nLow + numPatches - 1 */
|
||||
|
||||
uint8_t numPatches;
|
||||
uint8_t patchNumSubbands[5 + 1]; // [MAX_NUM_PATCHES + 1]
|
||||
uint8_t patchStartSubband[5 + 1]; // [MAX_NUM_PATCHES + 1]
|
||||
} SBRFreq;
|
||||
|
||||
typedef struct _SBRChan {
|
||||
int32_t reset;
|
||||
uint8_t deltaFlagEnv[5]; // [MAX_NUM_ENV]
|
||||
uint8_t deltaFlagNoise[2]; // [MAX_NUM_NOISE_FLOORS]
|
||||
int8_t envDataQuant[5][48]; // [MAX_NUM_ENV][MAX_QMF_BANDS] /* range = [0, 127] */
|
||||
int8_t noiseDataQuant[2][5]; // [MAX_NUM_NOISE_FLOORS][MAX_NUM_NOISE_FLOOR_BANDS]
|
||||
|
||||
uint8_t invfMode[2][5]; // [2][MAX_NUM_NOISE_FLOOR_BANDS] /* invfMode[0/1][band] = prev/curr */
|
||||
int32_t chirpFact[5]; // [MAX_NUM_NOISE_FLOOR_BANDS] /* bwArray */
|
||||
uint8_t addHarmonicFlag[2]; /* addHarmonicFlag[0/1] = prev/curr */
|
||||
uint8_t addHarmonic[2][64]; /* addHarmonic[0/1][band] = prev/curr */
|
||||
|
||||
int32_t gbMask[2]; /* gbMask[0/1] = XBuf[0-31]/XBuf[32-39] */
|
||||
int8_t laPrev;
|
||||
|
||||
int32_t noiseTabIndex;
|
||||
int32_t sinIndex;
|
||||
int32_t gainNoiseIndex;
|
||||
int32_t gTemp[5][48]; // [MAX_NUM_SMOOTH_COEFS][MAX_QMF_BANDS]
|
||||
int32_t qTemp[5][48]; // [MAX_NUM_SMOOTH_COEFS][MAX_QMF_BANDS]
|
||||
|
||||
} SBRChan;
|
||||
|
||||
|
||||
/* state info struct for baseline (MPEG-4 LC) decoding */
|
||||
typedef struct _PSInfoBase_t {
|
||||
int32_t dataCount;
|
||||
uint8_t dataBuf[510]; // [DATA_BUF_SIZE]
|
||||
int32_t fillCount;
|
||||
uint8_t fillBuf[269]; //[FILL_BUF_SIZE]
|
||||
/* state information which is the same throughout whole frame */
|
||||
int32_t nChans;
|
||||
int32_t useImpChanMap;
|
||||
int32_t sampRateIdx;
|
||||
/* state information which can be overwritten by subsequent elements within frame */
|
||||
ICSInfo_t icsInfo[2]; // [MAX_NCHANS_ELEM]
|
||||
int32_t commonWin;
|
||||
int16_t scaleFactors[2][15*8]; // [MAX_NCHANS_ELEM][MAX_SF_BANDS]
|
||||
uint8_t sfbCodeBook[2][15*8]; // [MAX_NCHANS_ELEM][MAX_SF_BANDS]
|
||||
int32_t msMaskPresent;
|
||||
uint8_t msMaskBits[(15 * 8 + 7) >> 3]; // [MAX_MS_MASK_BYTES]
|
||||
int32_t pnsUsed[2]; // [MAX_NCHANS_ELEM]
|
||||
int32_t pnsLastVal;
|
||||
int32_t intensityUsed[2]; // [MAX_NCHANS_ELEM]
|
||||
// PulseInfo_t pulseInfo[2]; // [MAX_NCHANS_ELEM]
|
||||
TNSInfo_t tnsInfo[2]; // [MAX_NCHANS_ELEM]
|
||||
int32_t tnsLPCBuf[20]; // [MAX_TNS_ORDER]
|
||||
int32_t tnsWorkBuf[20]; //[MAX_TNS_ORDER]
|
||||
GainControlInfo_t gainControlInfo[2]; // [MAX_NCHANS_ELEM]
|
||||
int32_t gbCurrent[2]; // [MAX_NCHANS_ELEM]
|
||||
int32_t coef[2][1024]; // [MAX_NCHANS_ELEM][AAC_MAX_NSAMPS]
|
||||
#ifdef AAC_ENABLE_SBR
|
||||
int32_t sbrWorkBuf[2][1024]; // [MAX_NCHANS_ELEM][AAC_MAX_NSAMPS];
|
||||
#endif
|
||||
/* state information which must be saved for each element and used in next frame */
|
||||
int32_t overlap[2][1024]; // [AAC_MAX_NCHANS][AAC_MAX_NSAMPS]
|
||||
int32_t prevWinShape[2]; // [AAC_MAX_NCHANS]
|
||||
} PSInfoBase_t;
|
||||
|
||||
typedef struct _PSInfoSBR {
|
||||
/* save for entire file */
|
||||
int32_t frameCount;
|
||||
int32_t sampRateIdx;
|
||||
|
||||
/* state info that must be saved for each channel */
|
||||
SBRHeader sbrHdr[2];
|
||||
SBRGrid sbrGrid[2];
|
||||
SBRFreq sbrFreq[2];
|
||||
SBRChan sbrChan[2];
|
||||
|
||||
/* temp variables, no need to save between blocks */
|
||||
uint8_t dataExtra;
|
||||
uint8_t resBitsData;
|
||||
uint8_t extendedDataPresent;
|
||||
int32_t extendedDataSize;
|
||||
|
||||
int8_t envDataDequantScale[2][5]; // [MAX_NCHANS_ELEM][MAX_NUM_ENV
|
||||
int32_t envDataDequant[2][5][48]; // [MAX_NCHANS_ELEM][MAX_NUM_ENV][MAX_QMF_BANDS
|
||||
int32_t noiseDataDequant[2][2][5]; // [MAX_NCHANS_ELEM][MAX_NUM_NOISE_FLOORS][MAX_NUM_NOISE_FLOOR_BANDS]
|
||||
|
||||
int32_t eCurr[48]; // [MAX_QMF_BANDS]
|
||||
uint8_t eCurrExp[48]; // [MAX_QMF_BANDS]
|
||||
uint8_t eCurrExpMax;
|
||||
int8_t la;
|
||||
|
||||
int32_t crcCheckWord;
|
||||
int32_t couplingFlag;
|
||||
int32_t envBand;
|
||||
int32_t eOMGainMax;
|
||||
int32_t gainMax;
|
||||
int32_t gainMaxFBits;
|
||||
int32_t noiseFloorBand;
|
||||
int32_t qp1Inv;
|
||||
int32_t qqp1Inv;
|
||||
int32_t sMapped;
|
||||
int32_t sBand;
|
||||
int32_t highBand;
|
||||
|
||||
int32_t sumEOrigMapped;
|
||||
int32_t sumECurrGLim;
|
||||
int32_t sumSM;
|
||||
int32_t sumQM;
|
||||
int32_t gLimBoost[48];
|
||||
int32_t qmLimBoost[48];
|
||||
int32_t smBoost[48];
|
||||
|
||||
int32_t smBuf[48];
|
||||
int32_t qmLimBuf[48];
|
||||
int32_t gLimBuf[48];
|
||||
int32_t gLimFbits[48];
|
||||
|
||||
int32_t gFiltLast[48];
|
||||
int32_t qFiltLast[48];
|
||||
|
||||
/* large buffers */
|
||||
int32_t delayIdxQMFA[2]; // [AAC_MAX_NCHANS]
|
||||
int32_t delayQMFA[2][10 * 32]; // [AAC_MAX_NCHANS][DELAY_SAMPS_QMFA]
|
||||
int32_t delayIdxQMFS[2]; // [AAC_MAX_NCHANS]
|
||||
int32_t delayQMFS[2][10 * 128]; // [AAC_MAX_NCHANS][DELAY_SAMPS_QMFS]
|
||||
int32_t XBufDelay[2][8][64][2]; // [AAC_MAX_NCHANS][HF_GEN][64][2]
|
||||
int32_t XBuf[32+8][64][2];
|
||||
} PSInfoSBR_t;
|
||||
|
||||
bool AACDecoder_AllocateBuffers(void);
|
||||
int32_t AACFlushCodec();
|
||||
void AACDecoder_FreeBuffers(void);
|
||||
bool AACDecoder_IsInit(void);
|
||||
int32_t AACFindSyncWord(uint8_t *buf, int32_t nBytes);
|
||||
int32_t AACSetRawBlockParams(int32_t nChans, int32_t sampRateCore, int32_t profile, int32_t copyLast = 0);
|
||||
int32_t AACDecode(uint8_t *inbuf, int32_t *bytesLeft, int16_t *outbuf);
|
||||
int32_t AACGetSampRate();
|
||||
int32_t AACGetChannels();
|
||||
int32_t AACGetID(); // 0-MPEG4, 1-MPEG2
|
||||
uint8_t AACGetProfile(); // 0-Main, 1-LC, 2-SSR, 3-reserved
|
||||
uint8_t AACGetFormat(); // 0-unknown 1-ADTS 2-ADIF, 3-RAW
|
||||
int32_t AACGetBitsPerSample();
|
||||
int32_t AACGetBitrate();
|
||||
int32_t AACGetOutputSamps();
|
||||
int32_t AACGetBitrate();
|
||||
void DecodeLPCCoefs(int32_t order, int32_t res, int8_t *filtCoef, int32_t *a, int32_t *b);
|
||||
int32_t FilterRegion(int32_t size, int32_t dir, int32_t order, int32_t *audioCoef, int32_t *a, int32_t *hist);
|
||||
int32_t TNSFilter(int32_t ch);
|
||||
int32_t DecodeSingleChannelElement();
|
||||
int32_t DecodeChannelPairElement();
|
||||
int32_t DecodeLFEChannelElement();
|
||||
int32_t DecodeDataStreamElement();
|
||||
int32_t DecodeProgramConfigElement(uint8_t idx);
|
||||
int32_t DecodeFillElement();
|
||||
int32_t DecodeNextElement(uint8_t **buf, int32_t *bitOffset, int32_t *bitsAvail);
|
||||
void PreMultiply(int32_t tabidx, int32_t *zbuf1);
|
||||
void PostMultiply(int32_t tabidx, int32_t *fft1);
|
||||
void PreMultiplyRescale(int32_t tabidx, int32_t *zbuf1, int32_t es);
|
||||
void PostMultiplyRescale(int32_t tabidx, int32_t *fft1, int32_t es);
|
||||
void DCT4(int32_t tabidx, int32_t *coef, int32_t gb);
|
||||
void BitReverse(int32_t *inout, int32_t tabidx);
|
||||
void R4FirstPass(int32_t *x, int32_t bg);
|
||||
void R8FirstPass(int32_t *x, int32_t bg);
|
||||
void R4Core(int32_t *x, int32_t bg, int32_t gp, int32_t *wtab);
|
||||
void R4FFT(int32_t tabidx, int32_t *x);
|
||||
void UnpackZeros(int32_t nVals, int32_t *coef);
|
||||
void UnpackQuads(int32_t cb, int32_t nVals, int32_t *coef);
|
||||
void UnpackPairsNoEsc(int32_t cb, int32_t nVals, int32_t *coef);
|
||||
void UnpackPairsEsc(int32_t cb, int32_t nVals, int32_t *coef);
|
||||
void DecodeSpectrumLong(int32_t ch);
|
||||
void DecodeSpectrumShort(int32_t ch);
|
||||
void DecWindowOverlap(int32_t *buf0, int32_t *over0, int16_t *pcm0, int32_t nChans, int32_t winTypeCurr, int32_t winTypePrev);
|
||||
void DecWindowOverlapLongStart(int32_t *buf0, int32_t *over0, int16_t *pcm0, int32_t nChans, int32_t winTypeCurr, int32_t winTypePrev);
|
||||
void DecWindowOverlapLongStop(int32_t *buf0, int32_t *over0, int16_t *pcm0, int32_t nChans, int32_t winTypeCurr, int32_t winTypePrev);
|
||||
void DecWindowOverlapShort(int32_t *buf0, int32_t *over0, int16_t *pcm0, int32_t nChans, int32_t winTypeCurr, int32_t winTypePrev);
|
||||
int32_t IMDCT(int32_t ch, int32_t chOut, int16_t *outbuf);
|
||||
void DecodeICSInfo(ICSInfo_t *icsInfo, int32_t sampRateIdx);
|
||||
void DecodeSectionData(int32_t winSequence, int32_t numWinGrp, int32_t maxSFB, uint8_t *sfbCodeBook);
|
||||
int32_t DecodeOneScaleFactor();
|
||||
void DecodeScaleFactors(int32_t numWinGrp, int32_t maxSFB, int32_t globalGain, uint8_t *sfbCodeBook, int16_t *scaleFactors);
|
||||
void DecodePulseInfo(uint8_t ch);
|
||||
void DecodeTNSInfo(int32_t winSequence, TNSInfo_t *ti, int8_t *tnsCoef);
|
||||
void DecodeGainControlInfo(int32_t winSequence, GainControlInfo_t *gi);
|
||||
void DecodeICS(int32_t ch);
|
||||
int32_t DecodeNoiselessData(uint8_t **buf, int32_t *bitOffset, int32_t *bitsAvail, int32_t ch);
|
||||
int32_t UnpackADTSHeader(uint8_t **buf, int32_t *bitOffset, int32_t *bitsAvail);
|
||||
int32_t GetADTSChannelMapping(uint8_t *buf, int32_t bitOffset, int32_t bitsAvail);
|
||||
int32_t GetNumChannelsADIF(int32_t nPCE);
|
||||
int32_t GetSampleRateIdxADIF(int32_t nPCE);
|
||||
int32_t UnpackADIFHeader(uint8_t **buf, int32_t *bitOffset, int32_t *bitsAvail);
|
||||
int32_t SetRawBlockParams(int32_t copyLast, int32_t nChans, int32_t sampRate, int32_t profile);
|
||||
int32_t PrepareRawBlock();
|
||||
int32_t DequantBlock(int32_t *inbuf, int32_t nSamps, int32_t scale);
|
||||
int32_t AACDequantize(int32_t ch);
|
||||
int32_t DeinterleaveShortBlocks(int32_t ch);
|
||||
uint32_t Get32BitVal(uint32_t *last);
|
||||
int32_t InvRootR(int32_t r);
|
||||
int32_t ScaleNoiseVector(int32_t *coef, int32_t nVals, int32_t sf);
|
||||
void GenerateNoiseVector(int32_t *coef, int32_t *last, int32_t nVals);
|
||||
void CopyNoiseVector(int32_t *coefL, int32_t *coefR, int32_t nVals);
|
||||
int32_t PNS(int32_t ch);
|
||||
int32_t GetSampRateIdx(int32_t sampRate);
|
||||
void StereoProcessGroup(int32_t *coefL, int32_t *coefR, const uint16_t *sfbTab, int32_t msMaskPres, uint8_t *msMaskPtr,
|
||||
int32_t msMaskOffset, int32_t maxSFB, uint8_t *cbRight, int16_t *sfRight, int32_t *gbCurrent);
|
||||
int32_t StereoProcess();
|
||||
int32_t RatioPowInv(int32_t a, int32_t b, int32_t c);
|
||||
int32_t SqrtFix(int32_t q, int32_t fBitsIn, int32_t *fBitsOut);
|
||||
int32_t InvRNormalized(int32_t r);
|
||||
void BitReverse32(int32_t *inout);
|
||||
void R8FirstPass32(int32_t *r0);
|
||||
void R4Core32(int32_t *r0);
|
||||
void FFT32C(int32_t *x);
|
||||
void CVKernel1(int32_t *XBuf, int32_t *accBuf);
|
||||
void CVKernel2(int32_t *XBuf, int32_t *accBuf);
|
||||
void SetBitstreamPointer(int32_t nBytes, uint8_t *buf);
|
||||
inline void RefillBitstreamCache();
|
||||
uint32_t GetBits(int32_t nBits);
|
||||
uint32_t GetBitsNoAdvance(int32_t nBits);
|
||||
void AdvanceBitstream(int32_t nBits);
|
||||
int32_t CalcBitsUsed(uint8_t *startBuf, int32_t startOffset);
|
||||
void ByteAlignBitstream();
|
||||
// SBR
|
||||
void InitSBRState();
|
||||
int32_t DecodeSBRBitstream(int32_t chBase);
|
||||
int32_t DecodeSBRData(int32_t chBase, int16_t *outbuf);
|
||||
int32_t FlushCodecSBR();
|
||||
void BubbleSort(uint8_t *v, int32_t nItems);
|
||||
uint8_t VMin(uint8_t *v, int32_t nItems);
|
||||
uint8_t VMax(uint8_t *v, int32_t nItems);
|
||||
int32_t CalcFreqMasterScaleZero(uint8_t *freqMaster, int32_t alterScale, int32_t k0, int32_t k2);
|
||||
int32_t CalcFreqMaster(uint8_t *freqMaster, int32_t freqScale, int32_t alterScale, int32_t k0, int32_t k2);
|
||||
int32_t CalcFreqHigh(uint8_t *freqHigh, uint8_t *freqMaster, int32_t nMaster, int32_t crossOverBand);
|
||||
int32_t CalcFreqLow(uint8_t *freqLow, uint8_t *freqHigh, int32_t nHigh);
|
||||
int32_t CalcFreqNoise(uint8_t *freqNoise, uint8_t *freqLow, int32_t nLow, int32_t kStart, int32_t k2, int32_t noiseBands);
|
||||
int32_t BuildPatches(uint8_t *patchNumSubbands, uint8_t *patchStartSubband, uint8_t *freqMaster, int32_t nMaster, int32_t k0,
|
||||
int32_t kStart, int32_t numQMFBands, int32_t sampRateIdx);
|
||||
int32_t FindFreq(uint8_t *freq, int32_t nFreq, uint8_t val);
|
||||
void RemoveFreq(uint8_t *freq, int32_t nFreq, int32_t removeIdx);
|
||||
int32_t CalcFreqLimiter(uint8_t *freqLimiter, uint8_t *patchNumSubbands, uint8_t *freqLow, int32_t nLow, int32_t kStart,
|
||||
int32_t limiterBands, int32_t numPatches);
|
||||
int32_t CalcFreqTables(SBRHeader *sbrHdr, SBRFreq *sbrFreq, int32_t sampRateIdx);
|
||||
void EstimateEnvelope(SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, int32_t env);
|
||||
int32_t GetSMapped(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int32_t env, int32_t band, int32_t la);
|
||||
void CalcMaxGain(SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, int32_t ch, int32_t env, int32_t lim, int32_t fbitsDQ);
|
||||
void CalcNoiseDivFactors(int32_t q, int32_t *qp1Inv, int32_t *qqp1Inv);
|
||||
void CalcComponentGains(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int32_t ch, int32_t env, int32_t lim, int32_t fbitsDQ);
|
||||
void ApplyBoost(SBRFreq *sbrFreq, int32_t lim, int32_t fbitsDQ);
|
||||
void CalcGain(SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int32_t ch, int32_t env);
|
||||
void MapHF(SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int32_t env, int32_t hfReset);
|
||||
void AdjustHighFreq(SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int32_t ch);
|
||||
int32_t CalcCovariance1(int32_t *XBuf, int32_t *p01reN, int32_t *p01imN, int32_t *p12reN, int32_t *p12imN, int32_t *p11reN, int32_t *p22reN);
|
||||
int32_t CalcCovariance2(int32_t *XBuf, int32_t *p02reN, int32_t *p02imN);
|
||||
void CalcLPCoefs(int32_t *XBuf, int32_t *a0re, int32_t *a0im, int32_t *a1re, int32_t *a1im, int32_t gb);
|
||||
void GenerateHighFreq(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int32_t ch);
|
||||
int32_t DecodeHuffmanScalar(const int16_t *huffTab, const HuffInfo_t *huffTabInfo, uint32_t bitBuf, int32_t *val);
|
||||
int32_t DecodeOneSymbol(int32_t huffTabIndex);
|
||||
int32_t DequantizeEnvelope(int32_t nBands, int32_t ampRes, int8_t *envQuant, int32_t *envDequant);
|
||||
void DequantizeNoise(int32_t nBands, int8_t *noiseQuant, int32_t *noiseDequant);
|
||||
void DecodeSBREnvelope(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int32_t ch);
|
||||
void DecodeSBRNoise(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int32_t ch);
|
||||
void UncoupleSBREnvelope(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR);
|
||||
void UncoupleSBRNoise(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR);
|
||||
void DecWindowOverlapNoClip(int32_t *buf0, int32_t *over0, int32_t *out0, int32_t winTypeCurr, int32_t winTypePrev);
|
||||
void DecWindowOverlapLongStartNoClip(int32_t *buf0, int32_t *over0, int32_t *out0, int32_t winTypeCurr, int32_t winTypePrev);
|
||||
void DecWindowOverlapLongStopNoClip(int32_t *buf0, int32_t *over0, int32_t *out0, int32_t winTypeCurr, int32_t winTypePrev);
|
||||
void DecWindowOverlapShortNoClip(int32_t *buf0, int32_t *over0, int32_t *out0, int32_t winTypeCurr, int32_t winTypePrev);
|
||||
void PreMultiply64(int32_t *zbuf1);
|
||||
void PostMultiply64(int32_t *fft1, int32_t nSampsOut);
|
||||
void QMFAnalysisConv(int32_t *cTab, int32_t *delay, int32_t dIdx, int32_t *uBuf);
|
||||
int32_t QMFAnalysis(int32_t *inbuf, int32_t *delay, int32_t *XBuf, int32_t fBitsIn, int32_t *delayIdx, int32_t qmfaBands);
|
||||
void QMFSynthesisConv(int32_t *cPtr, int32_t *delay, int32_t dIdx, int16_t *outbuf, int32_t nChans);
|
||||
void QMFSynthesis(int32_t *inbuf, int32_t *delay, int32_t *delayIdx, int32_t qmfsBands, int16_t *outbuf, int32_t nChans);
|
||||
int32_t UnpackSBRHeader(SBRHeader *sbrHdr);
|
||||
void UnpackSBRGrid(SBRHeader *sbrHdr, SBRGrid *sbrGrid);
|
||||
void UnpackDeltaTimeFreq(int32_t numEnv, uint8_t *deltaFlagEnv, int32_t numNoiseFloors, uint8_t *deltaFlagNoise);
|
||||
void UnpackInverseFilterMode(int32_t numNoiseFloorBands, uint8_t *mode);
|
||||
void UnpackSinusoids(int32_t nHigh, int32_t addHarmonicFlag, uint8_t *addHarmonic);
|
||||
void CopyCouplingGrid(SBRGrid *sbrGridLeft, SBRGrid *sbrGridRight);
|
||||
void CopyCouplingInverseFilterMode(int32_t numNoiseFloorBands, uint8_t *modeLeft, uint8_t *modeRight);
|
||||
void UnpackSBRSingleChannel(int32_t chBase);
|
||||
void UnpackSBRChannelPair(int32_t chBase);
|
||||
|
||||
inline uint8_t AACGetSBR(){return 0;}
|
||||
inline uint8_t AACGetParametricStereo(){return 0;}
|
||||
const char* AACGetErrorMessage(uint8_t errorCode);
|
||||
@@ -0,0 +1,606 @@
|
||||
// based om helix mp3 decoder
|
||||
#pragma once
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "../psram_unique_ptr.hpp"
|
||||
#include "assert.h"
|
||||
|
||||
extern __attribute__((weak)) void audio_info(const char*);
|
||||
|
||||
static const uint8_t m_HUFF_PAIRTABS =32;
|
||||
static const uint8_t m_BLOCK_SIZE =18;
|
||||
static const uint8_t m_NBANDS =32;
|
||||
static const uint8_t m_MAX_REORDER_SAMPS =(192-126)*3; // largest critical band for short blocks (see sfBandTable)
|
||||
static const uint16_t m_VBUF_LENGTH =17*2* m_NBANDS; // for double-sized vbuf FIFO
|
||||
static const uint8_t m_MAX_SCFBD =4; // max scalefactor bands per channel
|
||||
static const uint16_t m_MAINBUF_SIZE =1940;
|
||||
static const uint8_t m_MAX_NGRAN =2; // max granules
|
||||
static const uint8_t m_MAX_NCHAN =2; // max channels
|
||||
static const uint16_t m_MAX_NSAMP =576; // max samples per channel, per granule
|
||||
|
||||
enum {
|
||||
MP3_NONE = 0,
|
||||
MP3_ERR = -1,
|
||||
MP3_STOP = -100,
|
||||
};
|
||||
|
||||
typedef struct MP3FrameInfo {
|
||||
int32_t bitrate;
|
||||
int32_t nChans;
|
||||
int32_t samprate;
|
||||
int32_t bitsPerSample;
|
||||
int32_t outputSamps;
|
||||
int32_t layer;
|
||||
int32_t version;
|
||||
} MP3FrameInfo_t;
|
||||
|
||||
typedef struct SFBandTable {
|
||||
int32_t l[23];
|
||||
int32_t s[14];
|
||||
} SFBandTable_t;
|
||||
|
||||
typedef struct BitStreamInfo {
|
||||
uint8_t *bytePtr;
|
||||
uint32_t iCache;
|
||||
int32_t cachedBits;
|
||||
int32_t nBytes;
|
||||
} BitStreamInfo_t;
|
||||
|
||||
typedef enum { /* map these to the corresponding 2-bit values in the frame header */
|
||||
Stereo = 0x00, /* two independent channels, but L and R frames might have different # of bits */
|
||||
Joint = 0x01, /* coupled channels - layer III: mix of M-S and intensity, Layers I/II: intensity and direct coding only */
|
||||
Dual = 0x02, /* two independent channels, L and R always have exactly 1/2 the total bitrate */
|
||||
Mono = 0x03 /* one channel */
|
||||
} StereoMode_t;
|
||||
|
||||
typedef enum { /* map to 0,1,2 to make table indexing easier */
|
||||
MPEG1 = 0,
|
||||
MPEG2 = 1,
|
||||
MPEG25 = 2
|
||||
} MPEGVersion_t;
|
||||
|
||||
typedef struct FrameHeader {
|
||||
int32_t layer; /* layer index (1, 2, or 3) */
|
||||
int32_t crc; /* CRC flag: 0 = disabled, 1 = enabled */
|
||||
int32_t brIdx; /* bitrate index (0 - 15) */
|
||||
int32_t srIdx; /* sample rate index (0 - 2) */
|
||||
int32_t paddingBit; /* padding flag: 0 = no padding, 1 = single pad byte */
|
||||
int32_t privateBit; /* unused */
|
||||
int32_t modeExt; /* used to decipher joint stereo mode */
|
||||
int32_t copyFlag; /* copyright flag: 0 = no, 1 = yes */
|
||||
int32_t origFlag; /* original flag: 0 = copy, 1 = original */
|
||||
int32_t emphasis; /* deemphasis mode */
|
||||
int32_t CRCWord; /* CRC word (16 bits, 0 if crc not enabled) */
|
||||
} FrameHeader_t;
|
||||
|
||||
typedef struct SideInfoSub {
|
||||
int32_t part23Length; /* number of bits in main data */
|
||||
int32_t nBigvals; /* 2x this = first set of Huffman cw's (maximum amplitude can be > 1) */
|
||||
int32_t globalGain; /* overall gain for dequantizer */
|
||||
int32_t sfCompress; /* unpacked to figure out number of bits in scale factors */
|
||||
int32_t winSwitchFlag; /* window switching flag */
|
||||
int32_t blockType; /* block type */
|
||||
int32_t mixedBlock; /* 0 = regular block (all short or long), 1 = mixed block */
|
||||
int32_t tableSelect[3]; /* index of Huffman tables for the big values regions */
|
||||
int32_t subBlockGain[3]; /* subblock gain offset, relative to global gain */
|
||||
int32_t region0Count; /* 1+region0Count = num scale factor bands in first region of bigvals */
|
||||
int32_t region1Count; /* 1+region1Count = num scale factor bands in second region of bigvals */
|
||||
int32_t preFlag; /* for optional high frequency boost */
|
||||
int32_t sfactScale; /* scaling of the scalefactors */
|
||||
int32_t count1TableSelect; /* index of Huffman table for quad codewords */
|
||||
} SideInfoSub_t;
|
||||
|
||||
typedef struct SideInfo {
|
||||
int32_t mainDataBegin;
|
||||
int32_t privateBits;
|
||||
int32_t scfsi[m_MAX_NCHAN][m_MAX_SCFBD]; /* 4 scalefactor bands per channel */
|
||||
} SideInfo_t;
|
||||
|
||||
typedef struct {
|
||||
int32_t cbType; /* pure long = 0, pure short = 1, mixed = 2 */
|
||||
int32_t cbEndS[3]; /* number nonzero short cb's, per subbblock */
|
||||
int32_t cbEndSMax; /* max of cbEndS[] */
|
||||
int32_t cbEndL; /* number nonzero long cb's */
|
||||
} CriticalBandInfo_t;
|
||||
|
||||
typedef struct DequantInfo {
|
||||
int32_t workBuf[m_MAX_REORDER_SAMPS]; /* workbuf for reordering short blocks */
|
||||
} DequantInfo_t;
|
||||
|
||||
typedef struct HuffmanInfo {
|
||||
int32_t huffDecBuf[m_MAX_NCHAN][m_MAX_NSAMP]; /* used both for decoded Huffman values and dequantized coefficients */
|
||||
int32_t nonZeroBound[m_MAX_NCHAN]; /* number of coeffs in huffDecBuf[ch] which can be > 0 */
|
||||
int32_t gb[m_MAX_NCHAN]; /* minimum number of guard bits in huffDecBuf[ch] */
|
||||
} HuffmanInfo_t;
|
||||
|
||||
typedef enum HuffTabType {
|
||||
noBits,
|
||||
oneShot,
|
||||
loopNoLinbits,
|
||||
loopLinbits,
|
||||
quadA,
|
||||
quadB,
|
||||
invalidTab
|
||||
} HuffTabType_t;
|
||||
|
||||
typedef struct HuffTabLookup {
|
||||
int32_t linBits;
|
||||
int32_t tabType; /*HuffTabType*/
|
||||
} HuffTabLookup_t;
|
||||
|
||||
typedef struct IMDCTInfo {
|
||||
int32_t outBuf[m_MAX_NCHAN][m_BLOCK_SIZE][m_NBANDS]; /* output of IMDCT */
|
||||
int32_t overBuf[m_MAX_NCHAN][m_MAX_NSAMP / 2]; /* overlap-add buffer (by symmetry, only need 1/2 size) */
|
||||
int32_t numPrevIMDCT[m_MAX_NCHAN]; /* how many IMDCT's calculated in this channel on prev. granule */
|
||||
int32_t prevType[m_MAX_NCHAN];
|
||||
int32_t prevWinSwitch[m_MAX_NCHAN];
|
||||
int32_t gb[m_MAX_NCHAN];
|
||||
} IMDCTInfo_t;
|
||||
|
||||
typedef struct BlockCount {
|
||||
int32_t nBlocksLong;
|
||||
int32_t nBlocksTotal;
|
||||
int32_t nBlocksPrev;
|
||||
int32_t prevType;
|
||||
int32_t prevWinSwitch;
|
||||
int32_t currWinSwitch;
|
||||
int32_t gbIn;
|
||||
int32_t gbOut;
|
||||
} BlockCount_t;
|
||||
|
||||
typedef struct ScaleFactorInfoSub { /* max bits in scalefactors = 5, so use char's to save space */
|
||||
char l[23]; /* [band] */
|
||||
char s[13][3]; /* [band][window] */
|
||||
} ScaleFactorInfoSub_t;
|
||||
|
||||
typedef struct ScaleFactorJS { /* used in MPEG 2, 2.5 intensity (joint) stereo only */
|
||||
int32_t intensityScale;
|
||||
int32_t slen[4];
|
||||
int32_t nr[4];
|
||||
} ScaleFactorJS_t;
|
||||
|
||||
/* NOTE - could get by with smaller vbuf if memory is more important than speed
|
||||
* (in Subband, instead of replicating each block in FDCT32 you would do a memmove on the
|
||||
* last 15 blocks to shift them down one, a hardware style FIFO)
|
||||
*/
|
||||
typedef struct SubbandInfo {
|
||||
int32_t vbuf[m_MAX_NCHAN * m_VBUF_LENGTH]; /* vbuf for fast DCT-based synthesis PQMF - double size for speed (no modulo indexing) */
|
||||
int32_t vindex; /* internal index for tracking position in vbuf */
|
||||
} SubbandInfo_t;
|
||||
|
||||
typedef struct MP3DecInfo {
|
||||
/* buffer which must be large enough to hold largest possible main_data section */
|
||||
uint8_t mainBuf[m_MAINBUF_SIZE];
|
||||
/* special info for "free" bitrate files */
|
||||
int32_t freeBitrateFlag;
|
||||
int32_t freeBitrateSlots;
|
||||
/* user-accessible info */
|
||||
int32_t bitrate;
|
||||
int32_t nChans;
|
||||
int32_t samprate;
|
||||
int32_t nGrans; /* granules per frame */
|
||||
int32_t nGranSamps; /* samples per granule */
|
||||
int32_t nSlots;
|
||||
int32_t layer;
|
||||
|
||||
int32_t mainDataBegin;
|
||||
int32_t mainDataBytes;
|
||||
int32_t part23Length[m_MAX_NGRAN][m_MAX_NCHAN];
|
||||
} MP3DecInfo_t;
|
||||
|
||||
const uint16_t mpeg1_layer3_bitrates[16] = { // Bitraten-Lookup tables (example for MPEG1 Layer III)
|
||||
0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 // Attention: These tables must be complete and correct!
|
||||
}; // Index 0 is invalid, index 15 is invalid.
|
||||
|
||||
// SamplingFrequenz-Lookup tables(Beispiel für MPEG1, MPEG2, MPEG2.5)
|
||||
const uint16_t sampling_rates[3][4] = {
|
||||
{44100, 48000, 32000, 0}, // MPEG1
|
||||
{22050, 24000, 16000, 0}, // MPEG2
|
||||
{11025, 12000, 8000, 0} // MPEG2.5
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t mpeg_version; // 0=MPEG2.5, 1=reserved, 2=MPEG2, 3=MPEG1
|
||||
uint8_t layer; // 0=reserved, 1=Layer III, 2=Layer II, 3=Layer I
|
||||
bool crc_protected;
|
||||
uint8_t bitrate_idx;
|
||||
uint8_t sample_rate_idx;
|
||||
bool padding;
|
||||
uint8_t channel_mode;
|
||||
uint32_t frame_length; // In Bytes
|
||||
} Mp3FrameHeader;
|
||||
|
||||
|
||||
/* format = Q31
|
||||
* #define M_PI 3.14159265358979323846
|
||||
* double u = 2.0 * M_PI / 9.0;
|
||||
* float c0 = sqrt(3.0) / 2.0;
|
||||
* float c1 = cos(u);
|
||||
* float c2 = cos(2*u);
|
||||
* float c3 = sin(u);
|
||||
* float c4 = sin(2*u);
|
||||
*/
|
||||
|
||||
const int32_t c9_0 = 0x6ed9eba1;
|
||||
const int32_t c9_1 = 0x620dbe8b;
|
||||
const int32_t c9_2 = 0x163a1a7e;
|
||||
const int32_t c9_3 = 0x5246dd49;
|
||||
const int32_t c9_4 = 0x7e0e2e32;
|
||||
|
||||
|
||||
|
||||
const int32_t c3_0 = 0x6ed9eba1; /* format = Q31, cos(pi/6) */
|
||||
const int32_t c6[3] = { 0x7ba3751d, 0x5a82799a, 0x2120fb83 }; /* format = Q31, cos(((0:2) + 0.5) * (pi/6)) */
|
||||
|
||||
/* format = Q31
|
||||
* cos(((0:8) + 0.5) * (pi/18))
|
||||
*/
|
||||
const uint32_t c18[9] = { 0x7f834ed0, 0x7ba3751d, 0x7401e4c1, 0x68d9f964, 0x5a82799a, 0x496af3e2, 0x36185aee, 0x2120fb83, 0x0b27eb5c};
|
||||
|
||||
/* scale factor lengths (num bits) */
|
||||
const char m_SFLenTab[16][2] = { {0, 0}, {0, 1}, {0, 2}, {0, 3}, {3, 0}, {1, 1}, {1, 2}, {1, 3},
|
||||
{2, 1}, {2, 2}, {2, 3}, {3, 1}, {3, 2}, {3, 3}, {4, 2}, {4, 3}};
|
||||
|
||||
/* NRTab[size + 3*is_right][block type][partition]
|
||||
* block type index: 0 = (bt0,bt1,bt3), 1 = bt2 non-mixed, 2 = bt2 mixed
|
||||
* partition: scale factor groups (sfb1 through sfb4)
|
||||
* for block type = 2 (mixed or non-mixed) / by 3 is rolled into this table
|
||||
* (for 3 short blocks per long block)
|
||||
* see 2.4.3.2 in MPEG 2 (low sample rate) spec
|
||||
* stuff rolled into this table:
|
||||
* NRTab[x][1][y] --> (NRTab[x][1][y]) / 3
|
||||
* NRTab[x][2][>=1] --> (NRTab[x][2][>=1]) / 3 (first partition is long block)
|
||||
*/
|
||||
const char NRTab[6][3][4] = {
|
||||
{{ 6, 5, 5, 5}, {3, 3, 3, 3}, {6, 3, 3, 3}},
|
||||
{{ 6, 5, 7, 3}, {3, 3, 4, 2}, {6, 3, 4, 2}},
|
||||
{{11, 10, 0, 0}, {6, 6, 0, 0}, {6, 3, 6, 0}},
|
||||
{{ 7, 7, 7, 0}, {4, 4, 4, 0}, {6, 5, 4, 0}},
|
||||
{{ 6, 6, 6, 3}, {4, 3, 3, 2}, {6, 4, 3, 2}},
|
||||
{{ 8, 8, 5, 0}, {5, 4, 3, 0}, {6, 6, 3, 0}}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* optional pre-emphasis for high-frequency scale factor bands */
|
||||
const char preTab[22] = { 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0 };
|
||||
|
||||
/* pow(2,-i/4) for i=0..3, Q31 format */
|
||||
const int32_t pow14[4] PROGMEM = {
|
||||
0x7fffffff, 0x6ba27e65, 0x5a82799a, 0x4c1bf829
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Minimax polynomial approximation to pow(x, 4/3), over the range
|
||||
* poly43lo: x = [0.5, 0.7071]
|
||||
* poly43hi: x = [0.7071, 1.0]
|
||||
*
|
||||
* Relative error < 1E-7
|
||||
* Coefs are scaled by 4, 2, 1, 0.5, 0.25
|
||||
*/
|
||||
const uint32_t poly43lo[5] PROGMEM = { 0x29a0bda9, 0xb02e4828, 0x5957aa1b, 0x236c498d, 0xff581859 };
|
||||
const uint32_t poly43hi[5] PROGMEM = { 0x10852163, 0xd333f6a4, 0x46e9408b, 0x27c2cef0, 0xfef577b4 };
|
||||
|
||||
/* pow(2, i*4/3) as exp and frac */
|
||||
const int32_t pow2exp[8] PROGMEM = { 14, 13, 11, 10, 9, 7, 6, 5 };
|
||||
|
||||
const int32_t pow2frac[8] PROGMEM = {
|
||||
0x6597fa94, 0x50a28be6, 0x7fffffff, 0x6597fa94,
|
||||
0x50a28be6, 0x7fffffff, 0x6597fa94, 0x50a28be6
|
||||
};
|
||||
|
||||
const uint16_t m_HUFF_OFFSET_01= 0;
|
||||
const uint16_t m_HUFF_OFFSET_02= 9 + m_HUFF_OFFSET_01;
|
||||
const uint16_t m_HUFF_OFFSET_03= 65 + m_HUFF_OFFSET_02;
|
||||
const uint16_t m_HUFF_OFFSET_05= 65 + m_HUFF_OFFSET_03;
|
||||
const uint16_t m_HUFF_OFFSET_06=257 + m_HUFF_OFFSET_05;
|
||||
const uint16_t m_HUFF_OFFSET_07=129 + m_HUFF_OFFSET_06;
|
||||
const uint16_t m_HUFF_OFFSET_08=110 + m_HUFF_OFFSET_07;
|
||||
const uint16_t m_HUFF_OFFSET_09=280 + m_HUFF_OFFSET_08;
|
||||
const uint16_t m_HUFF_OFFSET_10= 93 + m_HUFF_OFFSET_09;
|
||||
const uint16_t m_HUFF_OFFSET_11=320 + m_HUFF_OFFSET_10;
|
||||
const uint16_t m_HUFF_OFFSET_12=296 + m_HUFF_OFFSET_11;
|
||||
const uint16_t m_HUFF_OFFSET_13=185 + m_HUFF_OFFSET_12;
|
||||
const uint16_t m_HUFF_OFFSET_15=497 + m_HUFF_OFFSET_13;
|
||||
const uint16_t m_HUFF_OFFSET_16=580 + m_HUFF_OFFSET_15;
|
||||
const uint16_t m_HUFF_OFFSET_24=651 + m_HUFF_OFFSET_16;
|
||||
|
||||
const int32_t huffTabOffset[m_HUFF_PAIRTABS] PROGMEM = {
|
||||
0, m_HUFF_OFFSET_01, m_HUFF_OFFSET_02, m_HUFF_OFFSET_03,
|
||||
0, m_HUFF_OFFSET_05, m_HUFF_OFFSET_06, m_HUFF_OFFSET_07,
|
||||
m_HUFF_OFFSET_08, m_HUFF_OFFSET_09, m_HUFF_OFFSET_10, m_HUFF_OFFSET_11,
|
||||
m_HUFF_OFFSET_12, m_HUFF_OFFSET_13, 0, m_HUFF_OFFSET_15,
|
||||
m_HUFF_OFFSET_16, m_HUFF_OFFSET_16, m_HUFF_OFFSET_16, m_HUFF_OFFSET_16,
|
||||
m_HUFF_OFFSET_16, m_HUFF_OFFSET_16, m_HUFF_OFFSET_16, m_HUFF_OFFSET_16,
|
||||
m_HUFF_OFFSET_24, m_HUFF_OFFSET_24, m_HUFF_OFFSET_24, m_HUFF_OFFSET_24,
|
||||
m_HUFF_OFFSET_24, m_HUFF_OFFSET_24, m_HUFF_OFFSET_24, m_HUFF_OFFSET_24,};
|
||||
|
||||
const HuffTabLookup_t huffTabLookup[m_HUFF_PAIRTABS] PROGMEM = {
|
||||
{ 0, noBits },
|
||||
{ 0, oneShot },
|
||||
{ 0, oneShot },
|
||||
{ 0, oneShot },
|
||||
{ 0, invalidTab },
|
||||
{ 0, oneShot },
|
||||
{ 0, oneShot },
|
||||
{ 0, loopNoLinbits },
|
||||
{ 0, loopNoLinbits },
|
||||
{ 0, loopNoLinbits },
|
||||
{ 0, loopNoLinbits },
|
||||
{ 0, loopNoLinbits },
|
||||
{ 0, loopNoLinbits },
|
||||
{ 0, loopNoLinbits },
|
||||
{ 0, invalidTab },
|
||||
{ 0, loopNoLinbits },
|
||||
{ 1, loopLinbits },
|
||||
{ 2, loopLinbits },
|
||||
{ 3, loopLinbits },
|
||||
{ 4, loopLinbits },
|
||||
{ 6, loopLinbits },
|
||||
{ 8, loopLinbits },
|
||||
{ 10, loopLinbits },
|
||||
{ 13, loopLinbits },
|
||||
{ 4, loopLinbits },
|
||||
{ 5, loopLinbits },
|
||||
{ 6, loopLinbits },
|
||||
{ 7, loopLinbits },
|
||||
{ 8, loopLinbits },
|
||||
{ 9, loopLinbits },
|
||||
{ 11, loopLinbits },
|
||||
{ 13, loopLinbits },
|
||||
};
|
||||
|
||||
|
||||
const int32_t quadTabOffset[2] PROGMEM = {0, 64};
|
||||
const int32_t quadTabMaxBits[2] PROGMEM = {6, 4};
|
||||
|
||||
/* indexing = [version][samplerate index]
|
||||
* sample rate of frame (Hz)
|
||||
*/
|
||||
const int32_t samplerateTab[3][3] PROGMEM = {
|
||||
{ 44100, 48000, 32000 }, /* MPEG-1 */
|
||||
{ 22050, 24000, 16000 }, /* MPEG-2 */
|
||||
{ 11025, 12000, 8000 }, /* MPEG-2.5 */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* indexing = [version][layer]
|
||||
* number of samples in one frame (per channel)
|
||||
*/
|
||||
const uint16_t samplesPerFrameTab[3][3] PROGMEM = { { 384, 1152, 1152 }, /* MPEG1 */
|
||||
{ 384, 1152, 576 }, /* MPEG2 */
|
||||
{ 384, 1152, 576 }, /* MPEG2.5 */
|
||||
};
|
||||
|
||||
/* layers 1, 2, 3 */
|
||||
const uint8_t bitsPerSlotTab[3] = { 32, 8, 8 };
|
||||
|
||||
/* indexing = [version][mono/stereo]
|
||||
* number of bytes in side info section of bitstream
|
||||
*/
|
||||
const uint8_t sideBytesTab[3][2] PROGMEM = { { 17, 32 }, /* MPEG-1: mono, stereo */
|
||||
{ 9, 17 }, /* MPEG-2: mono, stereo */
|
||||
{ 9, 17 }, /* MPEG-2.5: mono, stereo */
|
||||
};
|
||||
|
||||
/* indexing = [version][sampleRate][long (.l) or short (.s) block]
|
||||
* sfBandTable[v][s].l[cb] = index of first bin in critical band cb (long blocks)
|
||||
* sfBandTable[v][s].s[cb] = index of first bin in critical band cb (short blocks)
|
||||
*/
|
||||
const SFBandTable_t sfBandTable[3][3] PROGMEM = {
|
||||
{ /* MPEG-1 (44, 48, 32 kHz) */
|
||||
{ {0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90, 110, 134, 162, 196, 238, 288, 342, 418, 576 },
|
||||
{0, 4, 8, 12, 16, 22, 30, 40, 52, 66, 84, 106, 136, 192} },
|
||||
{ {0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88, 106, 128, 156, 190, 230, 276, 330, 384, 576 },
|
||||
{0, 4, 8, 12, 16, 22, 28, 38, 50, 64, 80, 100, 126, 192} },
|
||||
{ {0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82, 102, 126, 156, 194, 240, 296, 364, 448, 550, 576 },
|
||||
{0, 4, 8, 12, 16, 22, 30, 42, 58, 78, 104, 138, 180, 192} } },
|
||||
{ /* MPEG-2 (22, 24, 16 kHz) */
|
||||
{ {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 },
|
||||
{0, 4, 8, 12, 18, 24, 32, 42, 56, 74, 100, 132, 174, 192} },
|
||||
{ {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 114, 136, 162, 194, 232, 278, 332, 394, 464, 540, 576 },
|
||||
{0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 136, 180, 192} },
|
||||
{ {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 },
|
||||
{0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192} }, },
|
||||
{ /* MPEG-2.5 (11, 12, 8 kHz) */
|
||||
{ {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 },
|
||||
{0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192 } },
|
||||
{ {0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96, 116, 140, 168, 200, 238, 284, 336, 396, 464, 522, 576 },
|
||||
{0, 4, 8, 12, 18, 26, 36, 48, 62, 80, 104, 134, 174, 192 } },
|
||||
{ {0, 12, 24, 36, 48, 60, 72, 88, 108, 132, 160, 192, 232, 280, 336, 400, 476, 566, 568, 570, 572, 574, 576 },
|
||||
{0, 8, 16, 24, 36, 52, 72, 96, 124, 160, 162, 164, 166, 192 } }, },
|
||||
};
|
||||
|
||||
|
||||
/* indexing = [intensity scale on/off][left/right]
|
||||
* format = Q30, range = [0.0, 1.414]
|
||||
*
|
||||
* illegal intensity position scalefactors (see comments on ISFMpeg1)
|
||||
*/
|
||||
const int32_t ISFIIP[2][2] PROGMEM = {
|
||||
{0x40000000, 0x00000000}, /* mid-side off */
|
||||
{0x40000000, 0x40000000}, /* mid-side on */
|
||||
};
|
||||
|
||||
const uint8_t uniqueIDTab[8] = {0x5f, 0x4b, 0x43, 0x5f, 0x5f, 0x4a, 0x52, 0x5f};
|
||||
|
||||
/* anti-alias coefficients - see spec Annex B, table 3-B.9
|
||||
* csa[0][i] = CSi, csa[1][i] = CAi
|
||||
* format = Q31
|
||||
*/
|
||||
const uint32_t csa[8][2] PROGMEM = {
|
||||
{0x6dc253f0, 0xbe2500aa},
|
||||
{0x70dcebe4, 0xc39e4949},
|
||||
{0x798d6e73, 0xd7e33f4a},
|
||||
{0x7ddd40a7, 0xe8b71176},
|
||||
{0x7f6d20b7, 0xf3e4fe2f},
|
||||
{0x7fe47e40, 0xfac1a3c7},
|
||||
{0x7ffcb263, 0xfe2ebdc6},
|
||||
{0x7fffc694, 0xff86c25d},
|
||||
};
|
||||
|
||||
/* format = Q30, right shifted by 12 (sign bits only in top 12 - undo this when rounding to short)
|
||||
* this is to enable early-terminating multiplies on ARM
|
||||
* range = [-1.144287109, 1.144989014]
|
||||
* max gain of filter (per output sample) ~= 2.731
|
||||
*
|
||||
* new (properly sign-flipped) values
|
||||
* - these actually are correct to 32 bits, (floating-pt coefficients in spec
|
||||
* chosen such that only ~20 bits are required)
|
||||
*
|
||||
* Reordering - see table 3-B.3 in spec (appendix B)
|
||||
*
|
||||
* polyCoef[i] =
|
||||
* D[ 0, 32, 64, ... 480], i = [ 0, 15]
|
||||
* D[ 1, 33, 65, ... 481], i = [ 16, 31]
|
||||
* D[ 2, 34, 66, ... 482], i = [ 32, 47]
|
||||
* ...
|
||||
* D[15, 47, 79, ... 495], i = [240,255]
|
||||
*
|
||||
* also exploits symmetry: D[i] = -D[512 - i], for i = [1, 255]
|
||||
*
|
||||
* polyCoef[256, 257, ... 263] are for special case of sample 16 (out of 0)
|
||||
* see PolyphaseStereo() and PolyphaseMono()
|
||||
*/
|
||||
|
||||
static const char* mpeg_version_table[] = {
|
||||
"MPEG-2.5", // 0
|
||||
"reserved", // 1
|
||||
"MPEG-2", // 2
|
||||
"MPEG-1" // 3
|
||||
};
|
||||
|
||||
static const char* layer_table[] = {
|
||||
"Unknown", // 0
|
||||
"Layer I", // 1
|
||||
"Layer II", // 2
|
||||
"Layer III" // 3
|
||||
};
|
||||
|
||||
// prototypes
|
||||
bool MP3Decoder_AllocateBuffers(void);
|
||||
bool MP3Decoder_IsInit();
|
||||
void MP3Decoder_FreeBuffers();
|
||||
int32_t MP3Decode( uint8_t *inbuf, int32_t *bytesLeft, int16_t *outbuf);
|
||||
void MP3GetLastFrameInfo();
|
||||
int32_t MP3GetNextFrameInfo(uint8_t *buf);
|
||||
int32_t MP3FindSyncWord(uint8_t *buf, int32_t nBytes);
|
||||
int32_t MP3GetSampRate();
|
||||
int32_t MP3GetChannels();
|
||||
int32_t MP3GetBitsPerSample();
|
||||
int32_t MP3GetBitrate();
|
||||
int32_t MP3GetOutputSamps();
|
||||
const char* MP3GetLayer();
|
||||
const char* MP3GetMPEGVersion();
|
||||
|
||||
//internally used
|
||||
int MP3_AnalyzeFrame(const uint8_t *frame_data, size_t frame_len);
|
||||
void MP3Decoder_ClearBuffer(void);
|
||||
void PolyphaseMono(int16_t *pcm, int32_t *vbuf, const uint32_t* coefBase);
|
||||
void PolyphaseStereo(int16_t *pcm, int32_t *vbuf, const uint32_t* coefBase);
|
||||
void SetBitstreamPointer(BitStreamInfo_t *bsi, int32_t nBytes, uint8_t *buf);
|
||||
uint32_t GetBits(BitStreamInfo_t *bsi, int32_t nBits);
|
||||
int32_t CalcBitsUsed(BitStreamInfo_t *bsi, uint8_t *startBuf, int32_t startOffset);
|
||||
int32_t DequantChannel(int32_t *sampleBuf, int32_t *workBuf, int32_t *nonZeroBound, SideInfoSub_t *sis, ScaleFactorInfoSub_t *sfis, CriticalBandInfo_t *cbi);
|
||||
void MidSideProc(int32_t x[m_MAX_NCHAN][m_MAX_NSAMP], int32_t nSamps, int32_t mOut[2]);
|
||||
void IntensityProcMPEG1(int32_t x[m_MAX_NCHAN][m_MAX_NSAMP], int32_t nSamps, ScaleFactorInfoSub_t *sfis, CriticalBandInfo_t *cbi, int32_t midSideFlag, int32_t mixFlag, int32_t mOut[2]);
|
||||
void IntensityProcMPEG2(int32_t x[m_MAX_NCHAN][m_MAX_NSAMP], int32_t nSamps, ScaleFactorInfoSub_t *sfis, CriticalBandInfo_t *cbi, ScaleFactorJS_t *sfjs, int32_t midSideFlag, int32_t mixFlag, int32_t mOut[2]);
|
||||
void FDCT32(int32_t *x, int32_t *d, int32_t offset, int32_t oddBlock, int32_t gb);// __attribute__ ((section (".data")));
|
||||
int32_t CheckPadBit();
|
||||
int32_t UnpackFrameHeader(uint8_t *buf);
|
||||
int32_t UnpackSideInfo(uint8_t *buf);
|
||||
int32_t DecodeHuffman( uint8_t *buf, int32_t *bitOffset, int32_t huffBlockBits, int32_t gr, int32_t ch);
|
||||
int32_t MP3Dequantize( int32_t gr);
|
||||
int32_t IMDCT( int32_t gr, int32_t ch);
|
||||
int32_t UnpackScaleFactors( uint8_t *buf, int32_t *bitOffset, int32_t bitsAvail, int32_t gr, int32_t ch);
|
||||
int32_t Subband(int16_t *pcmBuf);
|
||||
int16_t ClipToShort(int32_t x, int32_t fracBits);
|
||||
void RefillBitstreamCache(BitStreamInfo_t *bsi);
|
||||
void UnpackSFMPEG1(BitStreamInfo_t *bsi, SideInfoSub_t *sis, ScaleFactorInfoSub_t *sfis, int32_t *scfsi, int32_t gr, ScaleFactorInfoSub_t *sfisGr0);
|
||||
void UnpackSFMPEG2(BitStreamInfo_t *bsi, SideInfoSub_t *sis, ScaleFactorInfoSub_t *sfis, int32_t gr, int32_t ch, int32_t modeExt, ScaleFactorJS_t *sfjs);
|
||||
int32_t MP3FindFreeSync(uint8_t *buf, uint8_t firstFH[4], int32_t nBytes);
|
||||
void MP3ClearBadFrame( int16_t *outbuf);
|
||||
int32_t DecodeHuffmanPairs(int32_t *xy, int32_t nVals, int32_t tabIdx, int32_t bitsLeft, uint8_t *buf, int32_t bitOffset);
|
||||
int32_t DecodeHuffmanQuads(int32_t *vwxy, int32_t nVals, int32_t tabIdx, int32_t bitsLeft, uint8_t *buf, int32_t bitOffset);
|
||||
int32_t DequantBlock(int32_t *inbuf, int32_t *outbuf, int32_t num, int32_t scale);
|
||||
void AntiAlias(int32_t *x, int32_t nBfly);
|
||||
void WinPrevious(int32_t *xPrev, int32_t *xPrevWin, int32_t btPrev);
|
||||
int32_t FreqInvertRescale(int32_t *y, int32_t *xPrev, int32_t blockIdx, int32_t es);
|
||||
void idct9(int32_t *x);
|
||||
int32_t IMDCT36(int32_t *xCurr, int32_t *xPrev, int32_t *y, int32_t btCurr, int32_t btPrev, int32_t blockIdx, int32_t gb);
|
||||
void imdct12(int32_t *x, int32_t *out);
|
||||
int32_t IMDCT12x3(int32_t *xCurr, int32_t *xPrev, int32_t *y, int32_t btPrev, int32_t blockIdx, int32_t gb);
|
||||
int32_t HybridTransform(int32_t *xCurr, int32_t *xPrev, int32_t y[m_BLOCK_SIZE][m_NBANDS], SideInfoSub_t *sis, BlockCount_t *bc);
|
||||
inline uint64_t SAR64(uint64_t x, int32_t n) {return x >> n;}
|
||||
inline int32_t MULSHIFT32(int32_t x, int32_t y) { int32_t z; z = (uint64_t) x * (uint64_t) y >> 32; return z;}
|
||||
inline uint64_t MADD64(uint64_t sum64, int32_t x, int32_t y) {sum64 += (uint64_t) x * (uint64_t) y; return sum64;}/* returns 64-bit value in [edx:eax] */
|
||||
inline uint64_t xSAR64(uint64_t x, int32_t n){return x >> n;}
|
||||
inline int32_t FASTABS(int32_t x){ return __builtin_abs(x);} //xtensa has a fast abs instruction //fb
|
||||
#define CLZ(x) __builtin_clz(x) //fb
|
||||
|
||||
// —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
|
||||
// 📌📌📌 L O G G I N G 📌📌📌
|
||||
|
||||
template <typename... Args>
|
||||
void MP3_ERROR_IMPL(uint8_t level, const char* path, int line, const char* fmt, Args&&... args) {
|
||||
extern __attribute__((weak)) void audio_info(const char*);
|
||||
#define ANSI_ESC_RESET "\033[0m"
|
||||
#define ANSI_ESC_BLACK "\033[30m"
|
||||
#define ANSI_ESC_RED "\033[31m"
|
||||
#define ANSI_ESC_GREEN "\033[32m"
|
||||
#define ANSI_ESC_YELLOW "\033[33m"
|
||||
#define ANSI_ESC_BLUE "\033[34m"
|
||||
#define ANSI_ESC_MAGENTA "\033[35m"
|
||||
#define ANSI_ESC_CYAN "\033[36m"
|
||||
#define ANSI_ESC_WHITE "\033[37m"
|
||||
|
||||
ps_ptr<char> result;
|
||||
ps_ptr<char> file;
|
||||
|
||||
file.copy_from(path);
|
||||
while(file.contains("/")){
|
||||
file.remove_before('/', false);
|
||||
}
|
||||
|
||||
// First run: determine size
|
||||
int len = std::snprintf(nullptr, 0, fmt, std::forward<Args>(args)...);
|
||||
if (len <= 0) return;
|
||||
|
||||
result.alloc(len + 1, "result");
|
||||
char* dst = result.get();
|
||||
if (!dst) return;
|
||||
std::snprintf(dst, len + 1, fmt, std::forward<Args>(args)...);
|
||||
|
||||
// build a final string with file/line prefix
|
||||
ps_ptr<char> final;
|
||||
int total_len = std::snprintf(nullptr, 0, "%s:%d:" ANSI_ESC_RED " %s" ANSI_ESC_RESET, file.c_get(), line, dst);
|
||||
if (total_len <= 0) return;
|
||||
final.alloc(total_len + 1, "final");
|
||||
char* dest = final.get();
|
||||
if (!dest) return; // Or error treatment
|
||||
if(audio_info){
|
||||
if (level == 1) snprintf(dest, total_len + 1, "%s:%d:" ANSI_ESC_RED " %s" ANSI_ESC_RESET, file.c_get(), line, dst);
|
||||
else if(level == 2) snprintf(dest, total_len + 1, "%s:%d:" ANSI_ESC_YELLOW " %s" ANSI_ESC_RESET, file.c_get(), line, dst);
|
||||
else if(level == 3) snprintf(dest, total_len + 1, "%s:%d:" ANSI_ESC_GREEN " %s" ANSI_ESC_RESET, file.c_get(), line, dst);
|
||||
else snprintf(dest, total_len + 1, "%s:%d:" ANSI_ESC_BLUE " %s" ANSI_ESC_RESET, file.c_get(), line, dst);
|
||||
audio_info(final.get());
|
||||
}
|
||||
else{
|
||||
std::snprintf(dest, total_len + 1, "%s:%d: %s", file.c_get(), line, dst);
|
||||
if (level == 1) log_e("%s", final.c_get());
|
||||
else if(level == 2) log_w("%s", final.c_get());
|
||||
else if(level == 3) log_i("%s", final.c_get());
|
||||
else log_d("%s", final.c_get());
|
||||
}
|
||||
final.reset();
|
||||
result.reset();
|
||||
}
|
||||
|
||||
// Macro for comfortable calls
|
||||
#define MP3_ERROR(fmt, ...) MP3_ERROR_IMPL(1, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define MP3_WARN(fmt, ...) MP3_ERROR_IMPL(2, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
#define MP3_INFO(fmt, ...) MP3_ERROR_IMPL(3, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
|
||||
// —————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
|
||||
|
||||