removed codecs to save memory

This commit is contained in:
2025-07-06 21:25:41 +02:00
parent 6022655198
commit fe04474ed8
104 changed files with 64077 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,763 @@
/*
* Audio.h
*
*/
#pragma once
#pragma GCC optimize ("Ofast")
#include "esp_arduino_version.h"
#include <vector>
#include <Arduino.h>
#include <libb64/cencode.h>
#include <esp32-hal-log.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#include <SD.h>
#include <SD_MMC.h>
#include <SPIFFS.h>
#include <FS.h>
#include <FFat.h>
#include <atomic>
#include <codecvt>
#include <locale>
#if ESP_ARDUINO_VERSION_MAJOR >= 3
#include <NetworkClient.h>
#include <NetworkClientSecure.h>
#endif
#if ESP_IDF_VERSION_MAJOR == 5
#include <driver/i2s_std.h>
#else
#include <driver/i2s.h>
#endif
#ifndef I2S_GPIO_UNUSED
#define I2S_GPIO_UNUSED -1 // = I2S_PIN_NO_CHANGE in IDF < 5
#endif
extern __attribute__((weak)) void audio_info(const char*);
extern __attribute__((weak)) void audio_id3data(const char*); //ID3 metadata
extern __attribute__((weak)) void audio_id3image(File& file, const size_t pos, const size_t size); //ID3 metadata image
extern __attribute__((weak)) void audio_oggimage(File& file, std::vector<uint32_t> v); //OGG blockpicture
extern __attribute__((weak)) void audio_id3lyrics(File& file, const size_t pos, const size_t size); //ID3 metadata lyrics
extern __attribute__((weak)) void audio_eof_mp3(const char*); //end of mp3 file
extern __attribute__((weak)) void audio_showstreamtitle(const char*);
extern __attribute__((weak)) void audio_showstation(const char*);
extern __attribute__((weak)) void audio_bitrate(const char*);
extern __attribute__((weak)) void audio_commercial(const char*);
extern __attribute__((weak)) void audio_icyurl(const char*);
extern __attribute__((weak)) void audio_icylogo(const char*);
extern __attribute__((weak)) void audio_icydescription(const char*);
extern __attribute__((weak)) void audio_lasthost(const char*);
extern __attribute__((weak)) void audio_eof_speech(const char*);
extern __attribute__((weak)) void audio_eof_stream(const char*); // The webstream comes to an end
extern __attribute__((weak)) void audio_process_i2s(int16_t* outBuff, uint16_t validSamples, uint8_t bitsPerSample, uint8_t channels, bool *continueI2S); // record audiodata or send via BT
extern __attribute__((weak)) void audio_log(uint8_t logLevel, const char* msg, const char* arg);
//----------------------------------------------------------------------------------------------------------------------
class AudioBuffer {
// AudioBuffer will be allocated in PSRAM, If PSRAM not available or has not enough space AudioBuffer will be
// allocated in FlashRAM with reduced size
//
// m_buffer m_readPtr m_writePtr m_endPtr
// | |<------dataLength------->|<------ writeSpace ----->|
// ▼ ▼ ▼ ▼
// ---------------------------------------------------------------------------------------------------------------
// | <--m_buffSize--> | <--m_resBuffSize --> |
// ---------------------------------------------------------------------------------------------------------------
// |<-----freeSpace------->| |<------freeSpace-------->|
//
//
//
// if the space between m_readPtr and buffend < m_resBuffSize copy data from the beginning to resBuff
// so that the mp3/aac/flac frame is always completed
//
// m_buffer m_writePtr m_readPtr m_endPtr
// | |<-------writeSpace------>|<--dataLength-->|
// ▼ ▼ ▼ ▼
// ---------------------------------------------------------------------------------------------------------------
// | <--m_buffSize--> | <--m_resBuffSize --> |
// ---------------------------------------------------------------------------------------------------------------
// |<--- ------dataLength-- ------>|<-------freeSpace------->|
//
//
public:
AudioBuffer(size_t maxBlockSize = 0); // constructor
~AudioBuffer(); // frees the buffer
size_t init(); // set default values
bool isInitialized() { return m_f_init; };
int32_t getBufsize();
void setBufsize(size_t mbs); // default is m_buffSizePSRAM for psram, and m_buffSizeRAM without psram
void changeMaxBlockSize(uint16_t mbs); // is default 1600 for mp3 and aac, set 16384 for FLAC
uint16_t getMaxBlockSize(); // returns maxBlockSize
size_t freeSpace(); // number of free bytes to overwrite
size_t writeSpace(); // space fom writepointer to bufferend
size_t bufferFilled(); // returns the number of filled bytes
size_t getMaxAvailableBytes(); // max readable bytes in one block
void bytesWritten(size_t bw); // update writepointer
void bytesWasRead(size_t br); // update readpointer
uint8_t* getWritePtr(); // returns the current writepointer
uint8_t* getReadPtr(); // returns the current readpointer
uint32_t getWritePos(); // write position relative to the beginning
uint32_t getReadPos(); // read position relative to the beginning
void resetBuffer(); // restore defaults
bool havePSRAM() { return m_f_psram; };
protected:
size_t m_buffSizePSRAM = UINT16_MAX * 10; // most webstreams limit the advance to 100...300Kbytes
size_t m_buffSizeRAM = 1600 * 10;
size_t m_buffSize = 0;
size_t m_freeSpace = 0;
size_t m_writeSpace = 0;
size_t m_dataLength = 0;
size_t m_resBuffSizeRAM = 4096; // reserved buffspace, >= one wav frame
size_t m_resBuffSizePSRAM = 4096 * 6; // reserved buffspace, >= one flac frame
size_t m_maxBlockSize = 1600;
uint8_t* m_buffer = NULL;
uint8_t* m_writePtr = NULL;
uint8_t* m_readPtr = NULL;
uint8_t* m_endPtr = NULL;
bool m_f_init = false;
bool m_f_isEmpty = true;
bool m_f_psram = false; // PSRAM is available (and used...)
};
//----------------------------------------------------------------------------------------------------------------------
static const size_t AUDIO_STACK_SIZE = 3300;
static StaticTask_t __attribute__((unused)) xAudioTaskBuffer;
static StackType_t __attribute__((unused)) xAudioStack[AUDIO_STACK_SIZE];
extern char audioI2SVers[];
class Audio : private AudioBuffer{
AudioBuffer InBuff; // instance of input buffer
public:
Audio(uint8_t i2sPort = I2S_NUM_0);
~Audio();
bool openai_speech(const String& api_key, const String& model, const String& input, const String& instructions, const String& voice, const String& response_format, const String& speed);
bool connecttohost(const char* host, const char* user = "", const char* pwd = "");
bool connecttospeech(const char* speech, const char* lang);
bool connecttoFS(fs::FS &fs, const char* path, int32_t m_fileStartPos = -1);
void setConnectionTimeout(uint16_t timeout_ms, uint16_t timeout_ms_ssl);
bool setAudioPlayPosition(uint16_t sec);
bool setFilePos(uint32_t pos);
bool setTimeOffset(int sec);
bool setPinout(uint8_t BCLK, uint8_t LRC, uint8_t DOUT, int8_t MCLK = I2S_GPIO_UNUSED);
bool pauseResume();
bool isRunning() {return m_f_running;}
void loop();
uint32_t stopSong();
void forceMono(bool m);
void setBalance(int8_t bal = 0);
void setVolumeSteps(uint8_t steps);
void setVolume(uint8_t vol, uint8_t curve = 0);
uint8_t getVolume();
uint8_t maxVolume();
uint8_t getI2sPort();
uint32_t getAudioDataStartPos();
uint32_t getFileSize();
uint32_t getFilePos();
uint32_t getSampleRate();
uint8_t getBitsPerSample();
uint8_t getChannels();
uint32_t getBitRate(bool avg = false);
uint32_t getAudioFileDuration();
uint32_t getAudioCurrentTime();
uint32_t getTotalPlayingTime();
uint16_t getVUlevel();
uint32_t inBufferFilled(); // returns the number of stored bytes in the inputbuffer
uint32_t inBufferFree(); // returns the number of free bytes in the inputbuffer
uint32_t inBufferSize(); // returns the size of the inputbuffer in bytes
void setBufferSize(size_t mbs); // sets the size of the inputbuffer in bytes
void setTone(int8_t gainLowPass, int8_t gainBandPass, int8_t gainHighPass);
void setI2SCommFMT_LSB(bool commFMT);
int getCodec() {return m_codec;}
const char *getCodecname() {return codecname[m_codec];}
const char *getVersion() {return audioI2SVers;}
private:
#ifndef ESP_ARDUINO_VERSION_VAL
#define ESP_ARDUINO_VERSION_MAJOR 0
#define ESP_ARDUINO_VERSION_MINOR 0
#define ESP_ARDUINO_VERSION_PATCH 0
#endif
enum : int8_t { AUDIOLOG_PATH_IS_NULL = -1, AUDIOLOG_FILE_NOT_FOUND = -2, AUDIOLOG_OUT_OF_MEMORY = -3, AUDIOLOG_FILE_READ_ERR = -4,
AUDIOLOG_M4A_ATOM_NOT_FOUND = -5, AUDIOLOG_ERR_UNKNOWN = -127 };
void UTF8toASCII(char* str);
bool latinToUTF8(char* buff, size_t bufflen, bool UTF8check = true);
void htmlToUTF8(char* str);
void setDefaults(); // free buffers and set defaults
void initInBuff();
bool httpPrint(const char* host);
bool httpRange(const char* host, uint32_t range);
void processLocalFile();
void processWebStream();
void processWebFile();
void processWebStreamTS();
void processWebStreamHLS();
void playAudioData();
bool readPlayListData();
const char* parsePlaylist_M3U();
const char* parsePlaylist_PLS();
const char* parsePlaylist_ASX();
const char* parsePlaylist_M3U8();
const char* m3u8redirection(uint8_t* codec);
uint64_t m3u8_findMediaSeqInURL();
bool STfromEXTINF(char* str);
void showCodecParams();
int findNextSync(uint8_t* data, size_t len);
int sendBytes(uint8_t* data, size_t len);
void setDecoderItems();
void computeAudioTime(uint16_t bytesDecoderIn, uint16_t bytesDecoderOut);
void printProcessLog(int r, const char* s = "");
void printDecodeError(int r);
void showID3Tag(const char* tag, const char* val);
size_t readAudioHeader(uint32_t bytes);
int read_WAV_Header(uint8_t* data, size_t len);
int read_ID3_Header(uint8_t* data, size_t len);
int read_M4A_Header(uint8_t* data, size_t len);
size_t process_m3u8_ID3_Header(uint8_t* packet);
bool setSampleRate(uint32_t hz);
bool setBitsPerSample(int bits);
bool setChannels(int channels);
void reconfigI2S();
bool setBitrate(int br);
void playChunk();
void computeVUlevel(int16_t sample[2]);
void computeLimit();
void Gain(int16_t* sample);
void showstreamtitle(char* ml);
bool parseContentType(char* ct);
bool parseHttpResponseHeader();
bool initializeDecoder(uint8_t codec);
esp_err_t I2Sstart();
esp_err_t I2Sstop();
void zeroI2Sbuff();
void IIR_filterChain0(int16_t iir_in[2], bool clear = false);
void IIR_filterChain1(int16_t iir_in[2], bool clear = false);
void IIR_filterChain2(int16_t iir_in[2], bool clear = false);
inline uint32_t streamavail() { return _client ? _client->available() : 0; }
void IIR_calculateCoefficients(int8_t G1, int8_t G2, int8_t G3);
bool ts_parsePacket(uint8_t* packet, uint8_t* packetStart, uint8_t* packetLength);
uint32_t find_m4a_atom(uint32_t fileSize, const char* atomType, uint32_t depth = 0);
//+++ create a T A S K for playAudioData(), output via I2S +++
public:
void setAudioTaskCore(uint8_t coreID);
uint32_t getHighWatermark();
private:
void startAudioTask(); // starts a task for decode and play
void stopAudioTask(); // stops task for audio
static void taskWrapper(void *param);
void audioTask();
void performAudioTask();
//+++ W E B S T R E A M - H E L P F U N C T I O N S +++
uint16_t readMetadata(uint16_t b, bool first = false);
size_t readChunkSize(uint8_t* bytes);
bool readID3V1Tag();
boolean streamDetection(uint32_t bytesAvail);
void seek_m4a_stsz();
void seek_m4a_ilst();
uint32_t m4a_correctResumeFilePos();
uint32_t ogg_correctResumeFilePos();
int32_t mp3_correctResumeFilePos();
uint8_t determineOggCodec(uint8_t* data, uint16_t len);
//++++ implement several function with respect to the index of string ++++
void strlower(char* str) {
unsigned char* p = (unsigned char*)str;
while(*p) {
*p = tolower((unsigned char)*p);
p++;
}
}
void trim(char *str) {
char *start = str; // keep the original pointer
char *end;
while (isspace((unsigned char)*start)) start++; // find the first non-space character
if (*start == 0) { // all characters were spaces
str[0] = '\0'; // return a empty string
return;
}
end = start + strlen(start) - 1; // find the end of the string
while (end > start && isspace((unsigned char)*end)) end--;
end[1] = '\0'; // Null-terminate the string after the last non-space character
// Move the trimmed string to the beginning of the memory area
memmove(str, start, strlen(start) + 1); // +1 for '\0'
}
bool startsWith (const char* base, const char* str) {
//fb
char c;
while ( (c = *str++) != '\0' )
if (c != *base++) return false;
return true;
}
bool endsWith(const char *base, const char *searchString) {
int32_t slen = strlen(searchString);
if(slen == 0) return false;
const char *p = base + strlen(base);
// while(p > base && isspace(*p)) p--; // rtrim
p -= slen;
if(p < base) return false;
return (strncmp(p, searchString, slen) == 0);
}
int indexOf (const char* base, const char* str, int startIndex = 0) {
//fb
const char *p = base;
for (; startIndex > 0; startIndex--)
if (*p++ == '\0') return -1;
char* pos = strstr(p, str);
if (pos == nullptr) return -1;
return pos - base;
}
int indexOf (const char* base, char ch, int startIndex = 0) {
//fb
const char *p = base;
for (; startIndex > 0; startIndex--)
if (*p++ == '\0') return -1;
char *pos = strchr(p, ch);
if (pos == nullptr) return -1;
return pos - base;
}
int lastIndexOf(const char* haystack, const char* needle) {
//fb
int nlen = strlen(needle);
if (nlen == 0) return -1;
const char *p = haystack - nlen + strlen(haystack);
while (p >= haystack) {
int i = 0;
while (needle[i] == p[i])
if (++i == nlen) return p - haystack;
p--;
}
return -1;
}
int lastIndexOf(const char* haystack, const char needle) {
//fb
const char *p = strrchr(haystack, needle);
return (p ? p - haystack : -1);
}
int specialIndexOf (uint8_t* base, const char* str, int baselen, bool exact = false){
int result = 0; // seek for str in buffer or in header up to baselen, not nullterninated
if (strlen(str) > baselen) return -1; // if exact == true seekstr in buffer must have "\0" at the end
for (int i = 0; i < baselen - strlen(str); i++){
result = i;
for (int j = 0; j < strlen(str) + exact; j++){
if (*(base + i + j) != *(str + j)){
result = -1;
break;
}
}
if (result >= 0) break;
}
return result;
}
int32_t min3(int32_t a, int32_t b, int32_t c){
uint32_t min_val = a;
if (b < min_val) min_val = b;
if (c < min_val) min_val = c;
return min_val;
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
// some other functions
uint64_t bigEndian(uint8_t* base, uint8_t numBytes, uint8_t shiftLeft = 8) {
uint64_t result = 0; // Use uint64_t for greater caching
if(numBytes < 1 || numBytes > 8) return 0;
for (int i = 0; i < numBytes; i++) {
result |= (uint64_t)(*(base + i)) << ((numBytes - i - 1) * shiftLeft); //Make sure the calculation is done correctly
}
if(result > SIZE_MAX) {
log_e("range overflow");
return 0;
}
return result;
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
bool b64encode(const char* source, uint16_t sourceLength, char* dest){
size_t size = base64_encode_expected_len(sourceLength) + 1;
char * buffer = (char *) malloc(size);
if(buffer) {
base64_encodestate _state;
base64_init_encodestate(&_state);
int len = base64_encode_block(&source[0], sourceLength, &buffer[0], &_state);
base64_encode_blockend((buffer + len), &_state);
memcpy(dest, buffer, strlen(buffer));
dest[strlen(buffer)] = '\0';
free(buffer);
return true;
}
return false;
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
void vector_clear_and_shrink(std::vector<char*>&vec){
uint size = vec.size();
for (int i = 0; i < size; i++) {
if(vec[i]){
free(vec[i]);
vec[i] = NULL;
}
}
vec.clear();
vec.shrink_to_fit();
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
uint32_t simpleHash(const char* str){
if(str == NULL) return 0;
uint32_t hash = 0;
for(int i=0; i<strlen(str); i++){
if(str[i] < 32) continue; // ignore control sign
hash += (str[i] - 31) * i * 32;
}
return hash;
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
char* x_ps_malloc(uint16_t len) {
char* ps_str = NULL;
if(psramFound()){ps_str = (char*) ps_malloc(len);}
else {ps_str = (char*) malloc(len);}
if(!ps_str) log_e("oom");
return ps_str;
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
char* x_ps_calloc(uint16_t len, uint8_t size) {
char* ps_str = NULL;
if(psramFound()){ps_str = (char*) ps_calloc(len, size);}
else {ps_str = (char*) calloc(len, size);}
if(!ps_str) log_e("oom");
return ps_str;
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
char* x_ps_realloc(char* ptr, uint16_t len) {
char* ps_str = NULL;
if(psramFound()){ps_str = (char*) ps_realloc(ptr, len);}
else {ps_str = (char*) realloc(ptr, len);}
if(!ps_str) log_e("oom");
return ps_str;
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
char* x_ps_strdup(const char* str) {
if(!str) {log_e("Input str is NULL"); return NULL;};
char* ps_str = NULL;
if(psramFound()) { ps_str = (char*)ps_malloc(strlen(str) + 1); }
else { ps_str = (char*)malloc(strlen(str) + 1); }
if(!ps_str){log_e("oom"); return NULL;}
strcpy(ps_str, str);
return ps_str;
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
void x_ps_free(char** b){
if(*b){free(*b); *b = NULL;}
}
void x_ps_free_const(const char** b) {
if (b && *b) {
free((void*)*b); // remove const
*b = NULL;
}
}
void x_ps_free(int16_t** b){
if(*b){free(*b); *b = NULL;}
}
void x_ps_free(uint8_t** b){
if(*b){free(*b); *b = NULL;}
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
char* urlencode(const char* str, bool spacesOnly) {
if (str == NULL) {
return NULL; // Eingabe ist NULL
}
// Reserve memory for the result (3x the length of the input string, worst-case)
size_t inputLength = strlen(str);
size_t bufferSize = inputLength * 3 + 1; // Worst-case-Szenario
char *encoded = (char *)x_ps_malloc(bufferSize);
if (encoded == NULL) {
return NULL; // memory allocation failed
}
const char *p_input = str; // Copy of the input pointer
char *p_encoded = encoded; // pointer of the output buffer
size_t remainingSpace = bufferSize; // remaining space in the output buffer
while (*p_input) {
if (isalnum((unsigned char)*p_input)) {
// adopt alphanumeric characters directly
if (remainingSpace > 1) {
*p_encoded++ = *p_input;
remainingSpace--;
} else {
free(encoded);
return NULL; // security check failed
}
} else if (spacesOnly && *p_input != 0x20) {
// Nur Leerzeichen nicht kodieren
if (remainingSpace > 1) {
*p_encoded++ = *p_input;
remainingSpace--;
} else {
free(encoded);
return NULL; // security check failed
}
} else {
// encode unsafe characters as '%XX'
if (remainingSpace > 3) {
int written = snprintf(p_encoded, remainingSpace, "%%%02X", (unsigned char)*p_input);
if (written < 0 || written >= (int)remainingSpace) {
free(encoded);
return NULL; // error writing to buffer
}
p_encoded += written;
remainingSpace -= written;
} else {
free(encoded);
return NULL; // security check failed
}
}
p_input++;
}
// Null-terminieren
if (remainingSpace > 0) {
*p_encoded = '\0';
} else {
free(encoded);
return NULL; // security check failed
}
return encoded;
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
// Function to reverse the byte order of a 32-bit value (big-endian to little-endian)
uint32_t bswap32(uint32_t x) {
return ((x & 0xFF000000) >> 24) |
((x & 0x00FF0000) >> 8) |
((x & 0x0000FF00) << 8) |
((x & 0x000000FF) << 24);
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
// Function to reverse the byte order of a 64-bit value (big-endian to little-endian)
uint64_t bswap64(uint64_t x) {
return ((x & 0xFF00000000000000ULL) >> 56) |
((x & 0x00FF000000000000ULL) >> 40) |
((x & 0x0000FF0000000000ULL) >> 24) |
((x & 0x000000FF00000000ULL) >> 8) |
((x & 0x00000000FF000000ULL) << 8) |
((x & 0x0000000000FF0000ULL) << 24) |
((x & 0x000000000000FF00ULL) << 40) |
((x & 0x00000000000000FFULL) << 56);
}
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
private:
const char *codecname[10] = {"unknown", "WAV", "MP3", "AAC", "M4A", "FLAC", "AACP", "OPUS", "OGG", "VORBIS" };
enum : int { APLL_AUTO = -1, APLL_ENABLE = 1, APLL_DISABLE = 0 };
enum : int { EXTERNAL_I2S = 0, INTERNAL_DAC = 1, INTERNAL_PDM = 2 };
enum : int { FORMAT_NONE = 0, FORMAT_M3U = 1, FORMAT_PLS = 2, FORMAT_ASX = 3, FORMAT_M3U8 = 4}; // playlist formats
enum : int { AUDIO_NONE, HTTP_RESPONSE_HEADER, AUDIO_DATA, AUDIO_LOCALFILE,
AUDIO_PLAYLISTINIT, AUDIO_PLAYLISTHEADER, AUDIO_PLAYLISTDATA};
enum : int { FLAC_BEGIN = 0, FLAC_MAGIC = 1, FLAC_MBH =2, FLAC_SINFO = 3, FLAC_PADDING = 4, FLAC_APP = 5,
FLAC_SEEK = 6, FLAC_VORBIS = 7, FLAC_CUESHEET = 8, FLAC_PICTURE = 9, FLAC_OKAY = 100};
enum : int { M4A_BEGIN = 0, M4A_FTYP = 1, M4A_CHK = 2, M4A_MOOV = 3, M4A_FREE = 4, M4A_TRAK = 5, M4A_MDAT = 6,
M4A_ILST = 7, M4A_MP4A = 8, M4A_AMRDY = 99, M4A_OKAY = 100};
enum : int { CODEC_NONE = 0, CODEC_WAV = 1, CODEC_MP3 = 2, CODEC_AAC = 3, CODEC_M4A = 4, CODEC_FLAC = 5,
CODEC_AACP = 6, CODEC_OPUS = 7, CODEC_OGG = 8, CODEC_VORBIS = 9};
enum : int { ST_NONE = 0, ST_WEBFILE = 1, ST_WEBSTREAM = 2};
typedef enum { LEFTCHANNEL=0, RIGHTCHANNEL=1 } SampleIndex;
typedef enum { LOWSHELF = 0, PEAKEQ = 1, HIFGSHELF =2 } FilterType;
typedef struct _filter{
float a0;
float a1;
float a2;
float b1;
float b2;
} filter_t;
typedef struct _pis_array{
int number;
int pids[4];
} pid_array;
File audiofile;
#ifndef ETHERNET_IF
WiFiClient client;
WiFiClientSecure clientsecure;
WiFiClient* _client = nullptr;
#else
NetworkClient client;
NetworkClientSecure clientsecure;
NetworkClient* _client = nullptr;
#endif
SemaphoreHandle_t mutex_playAudioData;
SemaphoreHandle_t mutex_audioTask;
TaskHandle_t m_audioTaskHandle = nullptr;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#if ESP_IDF_VERSION_MAJOR == 5
i2s_chan_handle_t m_i2s_tx_handle = {};
i2s_chan_config_t m_i2s_chan_cfg = {}; // stores I2S channel values
i2s_std_config_t m_i2s_std_cfg = {}; // stores I2S driver values
#else
i2s_config_t m_i2s_config = {};
i2s_pin_config_t m_pin_config = {};
#endif
#pragma GCC diagnostic pop
std::vector<char*> m_playlistContent; // m3u8 playlist buffer
std::vector<char*> m_playlistURL; // m3u8 streamURLs buffer
std::vector<uint32_t> m_hashQueue;
const size_t m_frameSizeWav = 4096;
const size_t m_frameSizeMP3 = 1600;
const size_t m_frameSizeAAC = 1600;
const size_t m_frameSizeVORBIS = 4096 * 2;
const size_t m_outbuffSize = 4096 * 2;
static const uint8_t m_tsPacketSize = 188;
static const uint8_t m_tsHeaderSize = 4;
char* m_ibuff = nullptr; // used in audio_info()
char* m_chbuf = NULL;
uint16_t m_chbufSize = 0; // will set in constructor (depending on PSRAM)
uint16_t m_ibuffSize = 0; // will set in constructor (depending on PSRAM)
char* m_lastHost = NULL; // Store the last URL to a webstream
char* m_lastM3U8host = NULL;
char* m_playlistBuff = NULL; // stores playlistdata
char* m_speechtxt = NULL; // stores tts text
const uint16_t m_plsBuffEntryLen = 256; // length of each entry in playlistBuff
filter_t m_filter[3]; // digital filters
int m_LFcount = 0; // Detection of end of header
uint32_t m_sampleRate=16000;
uint32_t m_bitRate=0; // current bitrate given fom decoder
uint32_t m_avr_bitrate = 0; // average bitrate, median computed by VBR
int m_readbytes = 0; // bytes read
uint32_t m_metacount = 0; // counts down bytes between metadata
int m_controlCounter = 0; // Status within readID3data() and readWaveHeader()
int8_t m_balance = 0; // -16 (mute left) ... +16 (mute right)
uint16_t m_vol = 21; // volume
uint16_t m_vol_steps = 21; // default
double m_limit_left = 0; // limiter 0 ... 1, left channel
double m_limit_right = 0; // limiter 0 ... 1, right channel
uint8_t m_timeoutCounter = 0; // timeout counter
uint8_t m_curve = 0; // volume characteristic
uint8_t m_bitsPerSample = 16; // bitsPerSample
uint8_t m_channels = 2;
uint8_t m_i2s_num = I2S_NUM_0; // I2S_NUM_0 or I2S_NUM_1
uint8_t m_playlistFormat = 0; // M3U, PLS, ASX
uint8_t m_codec = CODEC_NONE; //
uint8_t m_m3u8Codec = CODEC_AAC; // codec of m3u8 stream
uint8_t m_expectedCodec = CODEC_NONE; // set in connecttohost (e.g. http://url.mp3 -> CODEC_MP3)
uint8_t m_expectedPlsFmt = FORMAT_NONE; // set in connecttohost (e.g. streaming01.m3u) -> FORMAT_M3U)
uint8_t m_filterType[2]; // lowpass, highpass
uint8_t m_streamType = ST_NONE;
uint8_t m_ID3Size = 0; // lengt of ID3frame - ID3header
uint8_t m_vuLeft = 0; // average value of samples, left channel
uint8_t m_vuRight = 0; // average value of samples, right channel
uint8_t m_audioTaskCoreId = 0;
uint8_t m_M4A_objectType = 0; // set in read_M4A_Header
uint8_t m_M4A_chConfig = 0; // set in read_M4A_Header
uint16_t m_M4A_sampleRate = 0; // set in read_M4A_Header
int16_t* m_outBuff = NULL; // Interleaved L/R
int16_t m_validSamples = {0}; // #144
int16_t m_curSample{0};
uint16_t m_dataMode{0}; // Statemaschine
int16_t m_decodeError = 0; // Stores the return value of the decoder
uint16_t m_streamTitleHash = 0; // remember streamtitle, ignore multiple occurence in metadata
uint16_t m_timeout_ms = 250;
uint16_t m_timeout_ms_ssl = 2700;
uint32_t m_metaint = 0; // Number of databytes between metadata
uint32_t m_chunkcount = 0 ; // Counter for chunked transfer
uint32_t m_t0 = 0; // store millis(), is needed for a small delay
uint32_t m_contentlength = 0; // Stores the length if the stream comes from fileserver
uint32_t m_bytesNotDecoded = 0; // pictures or something else that comes with the stream
uint32_t m_PlayingStartTime = 0; // Stores the milliseconds after the start of the audio
int32_t m_resumeFilePos = -1; // the return value from stopSong(), (-1) is idle
int32_t m_fileStartPos = -1; // may be set in connecttoFS()
uint16_t m_m3u8_targetDuration = 10; //
uint32_t m_stsz_numEntries = 0; // num of entries inside stsz atom (uint32_t)
uint32_t m_stsz_position = 0; // pos of stsz atom within file
uint32_t m_haveNewFilePos = 0; // user changed the file position
uint32_t m_sumBytesDecoded = 0; // used for streaming
uint32_t m_webFilePos = 0; // same as audiofile.position() for SD files
bool m_f_metadata = false; // assume stream without metadata
bool m_f_unsync = false; // set within ID3 tag but not used
bool m_f_exthdr = false; // ID3 extended header
bool m_f_ssl = false;
bool m_f_running = false;
bool m_f_firstCall = false; // InitSequence for processWebstream and processLokalFile
bool m_f_firstCurTimeCall = false; // InitSequence for computeAudioTime
bool m_f_firstPlayCall = false; // InitSequence for playAudioData
bool m_f_firstM3U8call = false; // InitSequence for m3u8 parsing
bool m_f_ID3v1TagFound = false; // ID3v1 tag found
bool m_f_chunked = false ; // Station provides chunked transfer
bool m_f_firstmetabyte = false; // True if first metabyte (counter)
bool m_f_playing = false; // valid mp3 stream recognized
bool m_f_tts = false; // text to speech
bool m_f_ogg = false; // OGG stream
bool m_f_forceMono = false; // if true stereo -> mono
bool m_f_rtsp = false; // set if RTSP is used (m3u8 stream)
bool m_f_m3u8data = false; // used in processM3U8entries
bool m_f_Log = false; // set in platformio.ini -DAUDIO_LOG and -DCORE_DEBUG_LEVEL=3 or 4
bool m_f_continue = false; // next m3u8 chunk is available
bool m_f_ts = true; // transport stream
bool m_f_m4aID3dataAreRead = false; // has the m4a-ID3data already been read?
bool m_f_psramFound = false; // set in constructor, result of psramInit()
bool m_f_timeout = false; //
bool m_f_commFMT = false; // false: default (PHILIPS), true: Least Significant Bit Justified (japanese format)
bool m_f_audioTaskIsRunning = false;
bool m_f_allDataReceived = false;
bool m_f_stream = false; // stream ready for output?
bool m_f_decode_ready = false; // if true data for decode are ready
bool m_f_eof = false; // end of file
bool m_f_lockInBuffer = false; // lock inBuffer for manipulation
bool m_f_audioTaskIsDecoding = false;
bool m_f_acceptRanges = false;
bool m_f_reset_m3u8Codec = true; // reset codec for m3u8 stream
uint8_t m_f_channelEnabled = 3; //
uint32_t m_audioFileDuration = 0;
float m_audioCurrentTime = 0;
uint32_t m_audioDataStart = 0; // in bytes
size_t m_audioDataSize = 0; //
float m_filterBuff[3][2][2][2]; // IIR filters memory for Audio DSP
float m_corr = 1.0; // correction factor for level adjustment
size_t m_i2s_bytesWritten = 0; // set in i2s_write() but not used
size_t m_fileSize = 0; // size of the file
uint16_t m_filterFrequency[2];
int8_t m_gain0 = 0; // cut or boost filters (EQ)
int8_t m_gain1 = 0;
int8_t m_gain2 = 0;
pid_array m_pidsOfPMT;
int16_t m_pidOfAAC;
uint8_t m_packetBuff[m_tsPacketSize];
int16_t m_pesDataLength = 0;
};
//----------------------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,189 @@
/*
* aac_decoder.cpp
* faad2 - ESP32 adaptation
* Created on: 12.09.2023
* Updated on: 14.01.2025
*/
#include "Arduino.h"
#include "aac_decoder.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "libfaad/neaacdec.h"
// Declaration of the required global variables
NeAACDecHandle hAac;
NeAACDecFrameInfo frameInfo;
NeAACDecConfigurationPtr conf;
const uint8_t SYNCWORDH = 0xff; /* 12-bit syncword */
const uint8_t SYNCWORDL = 0xf0;
bool f_decoderIsInit = false;
bool f_firstCall = false;
bool f_setRaWBlockParams = false;
uint32_t aacSamplerate = 0;
uint8_t aacChannels = 0;
uint8_t aacProfile = 0;
static uint16_t validSamples = 0;
clock_t before;
float compressionRatio = 1;
mp4AudioSpecificConfig* mp4ASC;
//----------------------------------------------------------------------------------------------------------------------
bool AACDecoder_IsInit(){
return f_decoderIsInit;
}
//----------------------------------------------------------------------------------------------------------------------
bool AACDecoder_AllocateBuffers(){
before = clock();
hAac = NeAACDecOpen();
conf = NeAACDecGetCurrentConfiguration(hAac);
if(hAac) f_decoderIsInit = true;
f_firstCall = false;
f_setRaWBlockParams = false;
return f_decoderIsInit;
}
//----------------------------------------------------------------------------------------------------------------------
void AACDecoder_FreeBuffers(){
NeAACDecClose(hAac);
hAac = NULL;
f_decoderIsInit = false;
f_firstCall = false;
clock_t difference = clock() - before;
int msec = difference / CLOCKS_PER_SEC; (void)msec;
// printf("ms %li\n", difference);
}
//----------------------------------------------------------------------------------------------------------------------
uint8_t AACGetFormat(){
return frameInfo.header_type; // RAW 0 /* No header */
// ADIF 1 /* single ADIF header at the beginning of the file */
// ADTS 2 /* ADTS header at the beginning of each frame */
}
//----------------------------------------------------------------------------------------------------------------------
uint8_t AACGetSBR(){
return frameInfo.sbr; // NO_SBR 0 /* no SBR used in this file */
// SBR_UPSAMPLED 1 /* upsampled SBR used */
// SBR_DOWNSAMPLED 2 /* downsampled SBR used */
// NO_SBR_UPSAMPLED 3 /* no SBR used, but file is upsampled by a factor 2 anyway */
}
//----------------------------------------------------------------------------------------------------------------------
uint8_t AACGetParametricStereo(){ // not used (0) or used (1)
// log_w("frameInfo.ps %i", frameInfo.isPS);
return frameInfo.isPS;
}
//----------------------------------------------------------------------------------------------------------------------
int AACFindSyncWord(uint8_t *buf, int nBytes){
const int MIN_ADTS_HEADER_SIZE = 7;
auto validate = [](const uint8_t *buf) -> bool { // check the ADTS header for validity
// Layer (bits 14-15) must be 00
if ((buf[1] & 0x06) != 0x00) {
return false;
}
// Sampling Frequency Index (Bits 18-21) cannot be invalid
uint8_t sampling_frequency_index = (buf[2] & 0x3C) >> 2;
if (sampling_frequency_index > 12) {
return false;
}
// Frame length (bits 30-42) must be at least the header size
int frame_length = ((buf[3] & 0x03) << 11) | (buf[4] << 3) | ((buf[5] & 0xE0) >> 5);
if (frame_length < MIN_ADTS_HEADER_SIZE) {
return false;
}
return true;
};
/* find byte-aligned syncword (12 bits = 0xFFF) */
for (int i = 0; i < nBytes - 1; i++) {
if ( (buf[i+0] & SYNCWORDH) == SYNCWORDH && (buf[i+1] & SYNCWORDL) == SYNCWORDL ){
int frame_length = ((buf[i + 3] & 0x03) << 11) | (buf[i + 4] << 3) | ((buf[i + 5] & 0xE0) >> 5);
if (i + frame_length + MIN_ADTS_HEADER_SIZE > nBytes) {
return -1; // Puffergrenze überschritten, kein gültiger Header
}
/* find a second byte-aligned syncword (12 bits = 0xFFF) */
if ( (buf[i + frame_length + 0] & SYNCWORDH) == SYNCWORDH && (buf[i + frame_length + 1] & SYNCWORDL) == SYNCWORDL ){
return validate(&buf[i]) ? i : -1;
}
}
}
return -1;
}
//----------------------------------------------------------------------------------------------------------------------
int AACSetRawBlockParams(int nChans, int sampRateCore, int profile){
f_setRaWBlockParams = true;
aacChannels = nChans; // 1: Mono, 2: Stereo
aacSamplerate = (uint32_t)sampRateCore; // 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
aacProfile = profile; //1: AAC Main, 2: AAC LC (Low Complexity), 3: AAC SSR (Scalable Sample Rate), 4: AAC LTP (Long Term Prediction)
return 0;
}
//----------------------------------------------------------------------------------------------------------------------
int16_t AACGetOutputSamps(){
return validSamples;
}
//----------------------------------------------------------------------------------------------------------------------
int AACGetBitrate(){
uint32_t br = AACGetBitsPerSample() * AACGetChannels() * AACGetSampRate();
return (br / compressionRatio);;
}
//----------------------------------------------------------------------------------------------------------------------
int AACGetChannels(){
return aacChannels;
}
//----------------------------------------------------------------------------------------------------------------------
int AACGetSampRate(){
return aacSamplerate;
}
//----------------------------------------------------------------------------------------------------------------------
int AACGetBitsPerSample(){
return 16;
}
//----------------------------------------------------------------------------------------------------------------------
void createAudioSpecificConfig(uint8_t* config, uint8_t audioObjectType, uint8_t samplingFrequencyIndex, uint8_t channelConfiguration) {
config[0] = (audioObjectType << 3) | (samplingFrequencyIndex >> 1);
config[1] = (samplingFrequencyIndex << 7) | (channelConfiguration << 3);
}
//----------------------------------------------------------------------------------------------------------------------
extern uint8_t get_sr_index(const uint32_t samplerate);
int AACDecode(uint8_t *inbuf, int32_t *bytesLeft, short *outbuf){
uint8_t* ob = (uint8_t*)outbuf;
if (f_firstCall == false){
if(f_setRaWBlockParams){ // set raw AAC values, e.g. for M4A config.
f_setRaWBlockParams = false;
conf->defSampleRate = aacSamplerate;
conf->outputFormat = FAAD_FMT_16BIT;
conf->useOldADTSFormat = 1;
conf->defObjectType = 2;
int8_t ret = NeAACDecSetConfiguration(hAac, conf); (void)ret;
uint8_t specificInfo[2];
createAudioSpecificConfig(specificInfo, aacProfile, get_sr_index(aacSamplerate), aacChannels);
int8_t err = NeAACDecInit2(hAac, specificInfo, 2, &aacSamplerate, &aacChannels);(void)err;
}
else{
NeAACDecSetConfiguration(hAac, conf);
int8_t err = NeAACDecInit(hAac, inbuf, *bytesLeft, &aacSamplerate, &aacChannels); (void)err;
}
f_firstCall = true;
}
NeAACDecDecode2(hAac, &frameInfo, inbuf, *bytesLeft, (void**)&ob, 2048 * 2 * sizeof(int16_t));
*bytesLeft -= frameInfo.bytesconsumed;
validSamples = frameInfo.samples;
int8_t err = 0 - frameInfo.error;
compressionRatio = (float)frameInfo.samples * 2 / frameInfo.bytesconsumed;
return err;
}
//----------------------------------------------------------------------------------------------------------------------
const char* AACGetErrorMessage(int8_t err){
return NeAACDecGetErrorMessage(abs(err));
}
//----------------------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,34 @@
/*
* aac_decoder.h
* faad2 - ESP32 adaptation
* Created on: 12.09.2023
* Updated on: 13.08.2024
*/
#pragma once
#include <stdint.h>
#pragma GCC diagnostic warning "-Wunused-function"
struct AudioSpecificConfig {
uint8_t audioObjectType;
uint8_t samplingFrequencyIndex;
uint8_t channelConfiguration;
};
bool AACDecoder_IsInit();
bool AACDecoder_AllocateBuffers();
void AACDecoder_FreeBuffers();
uint8_t AACGetFormat();
uint8_t AACGetParametricStereo();
uint8_t AACGetSBR();
int AACFindSyncWord(uint8_t *buf, int nBytes);
int AACSetRawBlockParams(int nChans, int sampRateCore, int profile);
int16_t AACGetOutputSamps();
int AACGetBitrate();
int AACGetChannels();
int AACGetSampRate();
int AACGetBitsPerSample();
int AACDecode(uint8_t *inbuf, int32_t *bytesLeft, short *outbuf);
const char* AACGetErrorMessage(int8_t err);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,859 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
**
** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly forbidden.
**
** The "appropriate copyright message" mentioned in section 2c of the GPLv2 must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
**/
// ESP32 Version 29.07.2024
// updated: 10.05.2025
#pragma once
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>
/* ----------------------COMPILE TIME DEFINITIONS ---------------- */
#define PREFER_POINTERS // Use if target platform has address generators with autoincrement
// #define BIG_IQ_TABLE
// #define USE_DOUBLE_PRECISION // use double precision
#define FIXED_POINT // use fixed point reals, undefs MAIN_DEC and SSR_DEC
#define ERROR_RESILIENCE 2
#define MAIN_DEC // Allow decoding of MAIN profile AAC
// #define SSR_DEC // Allow decoding of SSR profile AAC
#define LTP_DEC // Allow decoding of LTP (Long Term Prediction) profile AAC
#define LD_DEC // Allow decoding of LD (Low Delay) profile AAC
// #define DRM_SUPPORT // Allow decoding of Digital Radio Mondiale (DRM)
#if (defined CONFIG_IDF_TARGET_ESP32S3 && defined BOARD_HAS_PSRAM)
#define SBR_DEC // Allow decoding of SBR (Spectral Band Replication) profile AAC
#define PS_DEC // Allow decoding of PS (Parametric Stereo) profile AAC
#endif
// #define SBR_LOW_POWER
#define ALLOW_SMALL_FRAMELENGTH
// #define LC_ONLY_DECODER // if you want a pure AAC LC decoder (independant of SBR_DEC and PS_DEC)
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#ifdef DRM_SUPPORT // Allow decoding of Digital Radio Mondiale (DRM)
#define DRM
#define DRM_PS
#endif
#ifdef LD_DEC /* LD can't do without LTP */
#ifndef ERROR_RESILIENCE
#define ERROR_RESILIENCE
#endif
#ifndef LTP_DEC
#define LTP_DEC
#endif
#endif
#ifdef LC_ONLY_DECODER
#undef LD_DEC
#undef LTP_DEC
#undef MAIN_DEC
#undef SSR_DEC
#undef DRM
#undef DRM_PS
#undef ALLOW_SMALL_FRAMELENGTH
#undef ERROR_RESILIENCE
#endif
#ifdef SBR_LOW_POWER
#undef PS_DEC
#endif
#ifdef FIXED_POINT /* No MAIN decoding */
#ifdef MAIN_DEC
#undef MAIN_DEC
#endif
#endif // FIXED_POINT
#ifdef DRM
#ifndef ALLOW_SMALL_FRAMELENGTH
#define ALLOW_SMALL_FRAMELENGTH
#endif
#undef LD_DEC
#undef LTP_DEC
#undef MAIN_DEC
#undef SSR_DEC
#endif
/* END COMPILE TIME DEFINITIONS */
#ifdef WORDS_BIGENDIAN
#define ARCH_IS_BIG_ENDIAN
#endif
/* FIXED_POINT doesn't work with MAIN and SSR yet */
#ifdef FIXED_POINT
#undef MAIN_DEC
#undef SSR_DEC
#endif
#if defined(FIXED_POINT)
#elif defined(USE_DOUBLE_PRECISION)
#else /* Normal floating point operation */
#ifdef HAVE_LRINTF
#define HAS_LRINTF
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#endif
#endif
#ifndef HAS_LRINTF
/* standard cast */
// #define int32_t(f) ((int32_t)(f))
#endif
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
/* defines if an object type can be decoded by this library or not */
__unused static uint8_t ObjectTypesTable[32] = {
0, /* 0 NULL */
#ifdef MAIN_DEC
1, /* 1 AAC Main */
#else
0, /* 1 AAC Main */
#endif
1, /* 2 AAC LC */
#ifdef SSR_DEC
1, /* 3 AAC SSR */
#else
0, /* 3 AAC SSR */
#endif
#ifdef LTP_DEC
1, /* 4 AAC LTP */
#else
0, /* 4 AAC LTP */
#endif
#ifdef SBR_DEC
1, /* 5 SBR */
#else
0, /* 5 SBR */
#endif
0, /* 6 AAC Scalable */
0, /* 7 TwinVQ */
0, /* 8 CELP */
0, /* 9 HVXC */
0, /* 10 Reserved */
0, /* 11 Reserved */
0, /* 12 TTSI */
0, /* 13 Main synthetic */
0, /* 14 Wavetable synthesis */
0, /* 15 General MIDI */
0, /* 16 Algorithmic Synthesis and Audio FX */
/* MPEG-4 Version 2 */
#ifdef ERROR_RESILIENCE
1, /* 17 ER AAC LC */
0, /* 18 (Reserved) */
#ifdef LTP_DEC
1, /* 19 ER AAC LTP */
#else
0, /* 19 ER AAC LTP */
#endif
0, /* 20 ER AAC scalable */
0, /* 21 ER TwinVQ */
0, /* 22 ER BSAC */
#ifdef LD_DEC
1, /* 23 ER AAC LD */
#else
0, /* 23 ER AAC LD */
#endif
0, /* 24 ER CELP */
0, /* 25 ER HVXC */
0, /* 26 ER HILN */
0, /* 27 ER Parametric */
#else /* No ER defined */
0, /* 17 ER AAC LC */
0, /* 18 (Reserved) */
0, /* 19 ER AAC LTP */
0, /* 20 ER AAC scalable */
0, /* 21 ER TwinVQ */
0, /* 22 ER BSAC */
0, /* 23 ER AAC LD */
0, /* 24 ER CELP */
0, /* 25 ER HVXC */
0, /* 26 ER HILN */
0, /* 27 ER Parametric */
#endif
0, /* 28 (Reserved) */
#ifdef PS_DEC
1, /* 29 AAC LC + SBR + PS */
#else
0, /* 29 AAC LC + SBR + PS */
#endif
0, /* 30 (Reserved) */
0 /* 31 (Reserved) */
};
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#define ZERO_HCB 0
#define FIRST_PAIR_HCB 5
#define ESC_HCB 11
#define QUAD_LEN 4
#define PAIR_LEN 2
#define NOISE_HCB 13
#define INTENSITY_HCB2 14
#define INTENSITY_HCB 15
#define DRC_REF_LEVEL 20 * 4 /* -20 dB */
#define DRM_PARAMETRIC_STEREO 0
#define DRM_NUM_SA_BANDS 8
#define DRM_NUM_PAN_BANDS 20
#define NUM_OF_LINKS 3
#define NUM_OF_QMF_CHANNELS 64
#define NUM_OF_SUBSAMPLES 30
#define MAX_SA_BAND 46
#define MAX_PAN_BAND 64
#define MAX_DELAY 5
#define EXTENSION_ID_PS 2
#define MAX_PS_ENVELOPES 5
#define NO_ALLPASS_LINKS 3
#define BYTE_NUMBIT 8
#define BYTE_NUMBIT_LD 3
#define bit2byte(a) ((a + 7) >> BYTE_NUMBIT_LD)
#define NUM_ERROR_MESSAGES 34
#define ESC_VAL 7
#define SSR_BANDS 4
#define PQFTAPS 96
#ifdef DRM
#define DECAY_CUTOFF 3
#define DECAY_SLOPE 0.05f
/* type definitaions */
typedef const int8_t (*drm_ps_huff_tab)[2];
#endif
#define FLOAT_SCALE (1.0f / (1 << 15))
#define DM_MUL REAL_CONST(0.3203772410170407) // 1/(1+sqrt(2) + 1/sqrt(2))
#define RSQRT2 REAL_CONST(0.7071067811865475244) // 1/sqrt(2)
#define NUM_CB 6
#define NUM_CB_ER 22
#define MAX_CB 32
#define VCB11_FIRST 16
#define VCB11_LAST 31
#define TNS_MAX_ORDER 20
#define MAIN 1
#define LC 2
#define SSR 3
#define LTP 4
#define HE_AAC 5
#define LD 23
#define ER_LC 17
#define ER_LTP 19
#define DRM_ER_LC 27 /* special object type for DRM */
/* header types */
#define RAW 0
#define ADIF 1
#define ADTS 2
#define LATM 3
/* SBR signalling */
#define NO_SBR 0
#define SBR_UPSAMPLED 1
#define SBR_DOWNSAMPLED 2
#define NO_SBR_UPSAMPLED 3
/* DRM channel definitions */
#define DRMCH_MONO 1
#define DRMCH_STEREO 2
#define DRMCH_SBR_MONO 3
#define DRMCH_SBR_STEREO 4
#define DRMCH_SBR_PS_STEREO 5
/* First object type that has ER */
#define ER_OBJECT_START 17
/* Bitstream */
#define LEN_SE_ID 3
#define LEN_TAG 4
#define LEN_BYTE 8
#define EXT_FIL 0
#define EXT_FILL_DATA 1
#define EXT_DATA_ELEMENT 2
#define EXT_DYNAMIC_RANGE 11
#define ANC_DATA 0
/* Syntax elements */
#define ID_SCE 0x0
#define ID_CPE 0x1
#define ID_CCE 0x2
#define ID_LFE 0x3
#define ID_DSE 0x4
#define ID_PCE 0x5
#define ID_FIL 0x6
#define ID_END 0x7
#define INVALID_ELEMENT_ID 255
#define ONLY_LONG_SEQUENCE 0x0
#define LONG_START_SEQUENCE 0x1
#define EIGHT_SHORT_SEQUENCE 0x2
#define LONG_STOP_SEQUENCE 0x3
#define ZERO_HCB 0
#define FIRST_PAIR_HCB 5
#define ESC_HCB 11
#define QUAD_LEN 4
#define PAIR_LEN 2
#define NOISE_HCB 13
#define INTENSITY_HCB2 14
#define INTENSITY_HCB 15
#define INVALID_SBR_ELEMENT 255
#define T_HFGEN 8
#define T_HFADJ 2
#define EXT_SBR_DATA 13
#define EXT_SBR_DATA_CRC 14
#define FIXFIX 0
#define FIXVAR 1
#define VARFIX 2
#define VARVAR 3
#define LO_RES 0
#define HI_RES 1
#define NO_TIME_SLOTS_960 15
#define NO_TIME_SLOTS 16
#define RATE 2
#define NOISE_FLOOR_OFFSET 6
#ifdef PS_DEC
#define NEGATE_IPD_MASK (0x1000)
#define DECAY_SLOPE FRAC_CONST(0.05)
#define COEF_SQRT2 COEF_CONST(1.4142135623731)
#endif // PS_DEC
#define MAX_NTSRHFG 40 /* MAX_NTSRHFG: maximum of number_time_slots * rate + HFGen. 16*2+8 */
#define MAX_NTSR 32 /* max number_time_slots * rate, ok for DRM and not DRM mode */
#define MAX_M 49 /* MAX_M: maximum value for M */
#define MAX_L_E 5 /* MAX_L_E: maximum value for L_E */
#ifdef SBR_DEC
#ifdef FIXED_POINT
#define _EPS (1) /* smallest number available in fixed point */
#else
#define _EPS (1e-12)
#endif
#endif // SBR_DEC
#ifdef FIXED_POINT /* int32_t */
#define LOG2_MIN_INF REAL_CONST(-10000)
#define COEF_BITS 28
#define COEF_PRECISION (1 << COEF_BITS)
#define REAL_BITS 14 // MAXIMUM OF 14 FOR FIXED POINT SBR
#define REAL_PRECISION (1 << REAL_BITS)
/* FRAC is the fractional only part of the fixed point number [0.0..1.0) */
#define FRAC_SIZE 32 /* frac is a 32 bit integer */
#define FRAC_BITS 31
#define FRAC_PRECISION ((uint32_t)(1 << FRAC_BITS))
#define FRAC_MAX 0x7FFFFFFF
typedef int32_t real_t;
#define REAL_CONST(A) (((A) >= 0) ? ((real_t)((A) * (REAL_PRECISION) + 0.5)) : ((real_t)((A) * (REAL_PRECISION) - 0.5)))
#define COEF_CONST(A) (((A) >= 0) ? ((real_t)((A) * (COEF_PRECISION) + 0.5)) : ((real_t)((A) * (COEF_PRECISION) - 0.5)))
#define FRAC_CONST(A) (((A) == 1.00) ? ((real_t)FRAC_MAX) : (((A) >= 0) ? ((real_t)((A) * (FRAC_PRECISION) + 0.5)) : ((real_t)((A) * (FRAC_PRECISION) - 0.5))))
// #define FRAC_CONST(A) (((A) >= 0) ? ((real_t)((A)*(FRAC_PRECISION)+0.5)) : ((real_t)((A)*(FRAC_PRECISION)-0.5)))
#define Q2_BITS 22
#define Q2_PRECISION (1 << Q2_BITS)
#define Q2_CONST(A) (((A) >= 0) ? ((real_t)((A) * (Q2_PRECISION) + 0.5)) : ((real_t)((A) * (Q2_PRECISION) - 0.5)))
/* multiply with real shift */
#define MUL_R(A, B) (real_t)(((int64_t)(A) * (int64_t)(B) + (1 << (REAL_BITS - 1))) >> REAL_BITS)
/* multiply with coef shift */
#define MUL_C(A, B) (real_t)(((int64_t)(A) * (int64_t)(B) + (1 << (COEF_BITS - 1))) >> COEF_BITS)
/* multiply with fractional shift */
#define _MulHigh(A, B) (real_t)(((int64_t)(A) * (int64_t)(B) + (1 << (FRAC_SIZE - 1))) >> FRAC_SIZE)
#define MUL_F(A, B) (real_t)(((int64_t)(A) * (int64_t)(B) + (1 << (FRAC_BITS - 1))) >> FRAC_BITS)
#define MUL_Q2(A, B) (real_t)(((int64_t)(A) * (int64_t)(B) + (1 << (Q2_BITS - 1))) >> Q2_BITS)
#define MUL_SHIFT6(A, B) (real_t)(((int64_t)(A) * (int64_t)(B) + (1 << (6 - 1))) >> 6)
#define MUL_SHIFT23(A, B) (real_t)(((int64_t)(A) * (int64_t)(B) + (1 << (23 - 1))) >> 23)
#define DIV_R(A, B) (((int64_t)A << REAL_BITS) / B)
#define DIV_C(A, B) (((int64_t)A << COEF_BITS) / B)
/* Complex multiplication */
static inline void ComplexMult(real_t* y1, real_t* y2, real_t x1, real_t x2, real_t c1, real_t c2) { // FIXED POINT
*y1 = (_MulHigh(x1, c1) + _MulHigh(x2, c2)) << (FRAC_SIZE - FRAC_BITS);
*y2 = (_MulHigh(x2, c1) - _MulHigh(x1, c2)) << (FRAC_SIZE - FRAC_BITS);
}
// static inline void ComplexMult(int32_t* y1, int32_t* y2, int32_t x1, int32_t x2, int32_t c1, int32_t c2) { // only XTENSA chips
// asm volatile (
// // y1 = (x1 * c1) + (x2 * c2)
// "mulsh a2, %2, %4\n" // a2 = x1 * c1 (Low 32 bits)
// "mulsh a3, %3, %5\n" // a3 = x2 * c2 (Low 32 bits)
// "add a2, a2, a3\n" // a2 = (x1 * c1) + (x2 * c2)
// "slli a2, a2, 1\n" // a2 = a2 >> 31 (Fixed-Point scaling)
// "s32i a2, %0 \n" // Store result in *y1
// // y2 = (x2 * c1) - (x1 * c2)
// "mulsh a2, %3, %4\n" // a2 = x2 * c1 (Low 32 bits)
// "mulsh a3, %2, %5\n" // a3 = x1 * c2 (Low 32 bits)
// "sub a2, a2, a3\n" // a2 = (x2 * c1) - (x1 * c2)
// "slli a2, a2, 1\n" // a2 = a2 >> 31 (Fixed-Point scaling)
// "s32i a2, %1 \n" // Store result in *y2
// : "=m" (*y1), "=m" (*y2) // Output
// : "r" (x1), "r" (x2), "r" (c1), "r" (c2) // Input
// : "a2", "a3" // Clobbers
// );
// }
#define DIV(A, B) (((int64_t)A << REAL_BITS) / B)
#define step(shift) \
if ((0x40000000l >> shift) + root <= value) { \
value -= (0x40000000l >> shift) + root; \
root = (root >> 1) | (0x40000000l >> shift); \
} else { \
root = root >> 1; \
}
real_t const pow2_table[] = {COEF_CONST(1.0), COEF_CONST(1.18920711500272), COEF_CONST(1.41421356237310), COEF_CONST(1.68179283050743)};
#endif // FIXED_POINT
#ifndef FIXED_POINT
#ifdef MAIN_DEC
#define ALPHA REAL_CONST(0.90625)
#define A REAL_CONST(0.953125)
#endif
#define IQ_TABLE_SIZE 8192
#define DIV_R(A, B) ((A) / (B))
#define DIV_C(A, B) ((A) / (B))
#ifdef USE_DOUBLE_PRECISION /* double */
typedef double real_t;
#include <math.h>
#define MUL_R(A, B) ((A) * (B))
#define MUL_C(A, B) ((A) * (B))
#define MUL_F(A, B) ((A) * (B))
/* Complex multiplication */
static void ComplexMult(real_t* y1, real_t* y2, real_t x1, real_t x2, real_t c1, real_t c2) {
*y1 = MUL_F(x1, c1) + MUL_F(x2, c2);
*y2 = MUL_F(x2, c1) - MUL_F(x1, c2);
}
#define REAL_CONST(A) ((real_t)(A))
#define COEF_CONST(A) ((real_t)(A))
#define Q2_CONST(A) ((real_t)(A))
#define FRAC_CONST(A) ((real_t)(A)) /* pure fractional part */
#else /* Normal floating point operation */
typedef float real_t;
#define MUL_R(A, B) ((A) * (B))
#define MUL_C(A, B) ((A) * (B))
#define MUL_F(A, B) ((A) * (B))
#define REAL_CONST(A) ((real_t)(A))
#define COEF_CONST(A) ((real_t)(A))
#define Q2_CONST(A) ((real_t)(A))
#define FRAC_CONST(A) ((real_t)(A)) /* pure fractional part */
/* Complex multiplication */
static void ComplexMult(real_t* y1, real_t* y2, real_t x1, real_t x2, real_t c1, real_t c2) {
*y1 = MUL_F(x1, c1) + MUL_F(x2, c2);
*y2 = MUL_F(x2, c1) - MUL_F(x1, c2);
}
#endif /* USE_DOUBLE_PRECISION */
#endif // FIXED_POINT
#ifdef SBR_LOW_POWER
#define qmf_t real_t
#define QMF_RE(A) (A)
#define QMF_IM(A)
#else
#define qmf_t complex_t
#define QMF_RE(A) RE(A)
#define QMF_IM(A) IM(A)
#endif
typedef real_t complex_t[2];
#define RE(A) A[0]
#define IM(A) A[1]
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#include "structs.h"
#include "tables.h"
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#ifndef FAAD2_VERSION
#define FAAD2_VERSION "unknown"
#endif
/* object types for AAC */
#define MAIN 1
#define LC 2
#define SSR 3
#define LTP 4
#define HE_AAC 5
#define ER_LC 17
#define ER_LTP 19
#define LD 23
#define DRM_ER_LC 27 /* special object type for DRM */
/* header types */
#define RAW 0
#define ADIF 1
#define ADTS 2
#define LATM 3
/* SBR signalling */
#define NO_SBR 0
#define SBR_UPSAMPLED 1
#define SBR_DOWNSAMPLED 2
#define NO_SBR_UPSAMPLED 3
/* library output formats */
#define FAAD_FMT_16BIT 1
#define FAAD_FMT_24BIT 2
#define FAAD_FMT_32BIT 3
#define FAAD_FMT_FLOAT 4
#define FAAD_FMT_FIXED FAAD_FMT_FLOAT
#define FAAD_FMT_DOUBLE 5
/* Capabilities */
#define LC_DEC_CAP (1<<0) /* Can decode LC */
#define MAIN_DEC_CAP (1<<1) /* Can decode MAIN */
#define LTP_DEC_CAP (1<<2) /* Can decode LTP */
#define LD_DEC_CAP (1<<3) /* Can decode LD */
#define ERROR_RESILIENCE_CAP (1<<4) /* Can decode ER */
#define FIXED_POINT_CAP (1<<5) /* Fixed point */
/* Channel definitions */
#define FRONT_CHANNEL_CENTER (1)
#define FRONT_CHANNEL_LEFT (2)
#define FRONT_CHANNEL_RIGHT (3)
#define SIDE_CHANNEL_LEFT (4)
#define SIDE_CHANNEL_RIGHT (5)
#define BACK_CHANNEL_LEFT (6)
#define BACK_CHANNEL_RIGHT (7)
#define BACK_CHANNEL_CENTER (8)
#define LFE_CHANNEL (9)
#define UNKNOWN_CHANNEL (0)
/* DRM channel definitions */
#define DRMCH_MONO 1
#define DRMCH_STEREO 2
#define DRMCH_SBR_MONO 3
#define DRMCH_SBR_STEREO 4
#define DRMCH_SBR_PS_STEREO 5
/* A decode call can eat up to FAAD_MIN_STREAMSIZE bytes per decoded channel,
so at least so much bytes per channel should be available in this stream */
#define FAAD_MIN_STREAMSIZE 768 /* 6144 bits/channel */
typedef void *NeAACDecHandle;
typedef struct mp4AudioSpecificConfig
{
/* Audio Specific Info */
unsigned char objectTypeIndex;
unsigned char samplingFrequencyIndex;
uint32_t samplingFrequency;
unsigned char channelsConfiguration;
/* GA Specific Info */
unsigned char frameLengthFlag;
unsigned char dependsOnCoreCoder;
unsigned short coreCoderDelay;
unsigned char extensionFlag;
unsigned char aacSectionDataResilienceFlag;
unsigned char aacScalefactorDataResilienceFlag;
unsigned char aacSpectralDataResilienceFlag;
unsigned char epConfig;
char sbr_present_flag;
char forceUpSampling;
char downSampledSBR;
} mp4AudioSpecificConfig;
typedef struct NeAACDecFrameInfo
{
uint32_t bytesconsumed;
uint32_t samples;
unsigned char channels;
unsigned char error;
uint32_t samplerate;
/* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */
unsigned char sbr;
/* MPEG-4 ObjectType */
unsigned char object_type;
/* AAC header type; MP4 will be signalled as RAW also */
unsigned char header_type;
/* multichannel configuration */
unsigned char num_front_channels;
unsigned char num_side_channels;
unsigned char num_back_channels;
unsigned char num_lfe_channels;
unsigned char channel_position[64];
/* PS: 0: off, 1: on */
unsigned char ps;
uint8_t isPS;
} NeAACDecFrameInfo;
uint8_t cpu_has_sse(void);
uint32_t ne_rng(uint32_t* __r1, uint32_t* __r2);
uint32_t wl_min_lzc(uint32_t x);
#ifdef FIXED_POINT
int32_t log2_int(uint32_t val);
int32_t log2_fix(uint32_t val);
int32_t pow2_int(real_t val);
real_t pow2_fix(real_t val);
#endif
uint8_t get_sr_index(const uint32_t samplerate);
uint8_t max_pred_sfb(const uint8_t sr_index);
uint8_t max_tns_sfb(const uint8_t sr_index, const uint8_t object_type, const uint8_t is_short);
uint32_t get_sample_rate(const uint8_t sr_index);
int8_t can_decode_ot(const uint8_t object_type);
void* faad_malloc(size_t size);
template <typename freeType>
void faad_free(freeType** b);
drc_info* drc_init(real_t cut, real_t boost);
void drc_end(drc_info* drc);
void drc_decode(drc_info* drc, real_t* spec);
sbr_info* sbrDecodeInit(uint16_t framelength, uint8_t id_aac, uint32_t sample_rate, uint8_t downSampledSBR, uint8_t IsDRM);
void sbrDecodeEnd(sbr_info* sbr);
void sbrReset(sbr_info* sbr);
uint8_t sbrDecodeCoupleFrame(sbr_info* sbr, real_t* left_chan, real_t* right_chan, const uint8_t just_seeked, const uint8_t downSampledSBR);
uint8_t sbrDecodeSingleFrame(sbr_info* sbr, real_t* channel, const uint8_t just_seeked, const uint8_t downSampledSBR);
uint16_t ps_data(ps_info* ps, bitfile* ld, uint8_t* header);
ps_info* ps_init(uint8_t sr_index, uint8_t numTimeSlotsRate);
void ps_free(ps_info* ps);
uint8_t ps_decode(ps_info* ps, qmf_t X_left[38][64], qmf_t X_right[38][64]);
void faad_initbits(bitfile* ld, const void* buffer, const uint32_t buffer_size);
void faad_endbits(bitfile* ld);
void faad_initbits_rev(bitfile* ld, void* buffer, uint32_t bits_in_buffer);
uint8_t faad_byte_align(bitfile* ld);
uint32_t faad_get_processed_bits(bitfile* ld);
void faad_flushbits_ex(bitfile* ld, uint32_t bits);
void faad_rewindbits(bitfile* ld);
void faad_resetbits(bitfile* ld, int bits);
uint8_t* faad_getbitbuffer(bitfile* ld, uint32_t bits);
void* faad_origbitbuffer(bitfile* ld);
uint32_t faad_origbitbuffer_size(bitfile* ld);
uint8_t faad_get1bit(bitfile* ld);
uint32_t faad_getbits(bitfile* ld, uint32_t n);
uint32_t faad_showbits_rev(bitfile* ld, uint32_t bits);
void faad_flushbits_rev(bitfile* ld, uint32_t bits);
uint32_t getdword(void* mem);
uint32_t getdword_n(void* mem, int n);
void faad_flushbits(bitfile* ld, uint32_t bits);
uint32_t faad_showbits(bitfile* ld, uint32_t bits);
uint32_t showbits_hcr(bits_t* ld, uint8_t bits);
uint32_t faad_getbits_rev(bitfile* ld, uint32_t n);
int8_t get1bit_hcr(bits_t* ld, uint8_t* result);
int8_t flushbits_hcr(bits_t* ld, uint8_t bits);
int8_t getbits_hcr(bits_t* ld, uint8_t n, uint32_t* result);
void cfftf(cfft_info* cfft, complex_t* c);
void cfftb(cfft_info* cfft, complex_t* c);
cfft_info* cffti(uint16_t n);
void cfftu(cfft_info* cfft);
NeAACDecHandle NeAACDecOpen(void);
const char* NeAACDecGetErrorMessage(unsigned const char errcode);
void* NeAACDecDecode2(NeAACDecHandle hpDecoder, NeAACDecFrameInfo* hInfo, unsigned char* buffer, uint32_t buffer_size, void** sample_buffer, uint32_t sample_buffer_size);
long NeAACDecInit(NeAACDecHandle hpDecoder, unsigned char* buffer, uint32_t buffer_size, uint32_t* samplerate, unsigned char* channels);
unsigned char NeAACDecSetConfiguration(NeAACDecHandle hpDecoder, NeAACDecConfigurationPtr config);
char NeAACDecInit2(NeAACDecHandle hpDecoder, unsigned char* pBuffer, uint32_t SizeOfDecoderSpecificInfo, uint32_t* samplerate, unsigned char* channels);
unsigned char NeAACDecSetConfiguration(NeAACDecHandle hpDecoder, NeAACDecConfigurationPtr config);
void NeAACDecClose(NeAACDecHandle hpDecoder);
NeAACDecConfigurationPtr NeAACDecGetCurrentConfiguration(NeAACDecHandle hpDecoder);
void* aac_frame_decode(NeAACDecStruct* hDecoder, NeAACDecFrameInfo* hInfo, unsigned char* buffer, uint32_t buffer_size, void** sample_buffer2, uint32_t sample_buffer_size);
void create_channel_config(NeAACDecStruct* hDecoder, NeAACDecFrameInfo* hInfo);
void ssr_filter_bank_end(fb_info* fb);
void passf2pos(const uint16_t ido, const uint16_t l1, const complex_t* cc, complex_t* ch, const complex_t* wa);
void passf2neg(const uint16_t ido, const uint16_t l1, const complex_t* cc, complex_t* ch, const complex_t* wa);
void passf3(const uint16_t ido, const uint16_t l1, const complex_t* cc, complex_t* ch, const complex_t* wa1, const complex_t* wa2, const int8_t isign);
void passf4pos(const uint16_t ido, const uint16_t l1, const complex_t* cc, complex_t* ch, const complex_t* wa1, const complex_t* wa2, const complex_t* wa3);
void passf4neg(const uint16_t ido, const uint16_t l1, const complex_t* cc, complex_t* ch, const complex_t* wa1, const complex_t* wa2, const complex_t* wa3);
void passf5(const uint16_t ido, const uint16_t l1, const complex_t* cc, complex_t* ch, const complex_t* wa1, const complex_t* wa2, const complex_t* wa3, const complex_t* wa4, const int8_t isign);
void cffti1(uint16_t n, complex_t* wa, uint16_t* ifac);
drc_info *drc_init(real_t cut, real_t boost);
void drc_end(drc_info *drc);
void drc_decode(drc_info *drc, real_t *spec);
fb_info* filter_bank_init(uint16_t frame_len);
void filter_bank_end(fb_info* fb);
void filter_bank_ltp(fb_info* fb, uint8_t window_sequence, uint8_t window_shape, uint8_t window_shape_prev, real_t* in_data, real_t* out_mdct, uint8_t object_type, uint16_t frame_len);
void ifilter_bank(fb_info* fb, uint8_t window_sequence, uint8_t window_shape, uint8_t window_shape_prev, real_t* freq_in, real_t* time_out, real_t* overlap, uint8_t object_type, uint16_t frame_len);
void ms_decode(ic_stream *ics, ic_stream *icsr, real_t *l_spec, real_t *r_spec, uint16_t frame_len);
void is_decode(ic_stream* ics, ic_stream* icsr, real_t* l_spec, real_t* r_spec, uint16_t frame_len);
int8_t is_intensity(ic_stream* ics, uint8_t group, uint8_t sfb);
uint8_t is_noise(ic_stream *ics, uint8_t group, uint8_t sfb);
real_t fp_sqrt(real_t value);
void pns_decode(ic_stream* ics_left, ic_stream* ics_right, real_t* spec_left, real_t* spec_right, uint16_t frame_len, uint8_t channel_pair, uint8_t object_type,
/* RNG states */ uint32_t* __r1, uint32_t* __r2);
int8_t invert_intensity(ic_stream* ics, uint8_t group, uint8_t sfb);
void* output_to_PCM(NeAACDecStruct* hDecoder, real_t** input, void* samplebuffer, uint8_t channels, uint16_t frame_len, uint8_t format);
uint8_t pulse_decode(ic_stream *ics, int16_t *spec_coef, uint16_t framelen);
void gen_rand_vector(real_t* spec, int16_t scale_factor, uint16_t size, uint8_t sub, uint32_t* __r1, uint32_t* __r2);
void huffman_sign_bits(bitfile *ld, int16_t *sp, uint8_t len);
uint8_t huffman_getescape(bitfile *ld, int16_t *sp);
uint8_t huffman_2step_quad(uint8_t cb, bitfile *ld, int16_t *sp);
uint8_t huffman_2step_quad_sign(uint8_t cb, bitfile *ld, int16_t *sp);
uint8_t huffman_2step_pair(uint8_t cb, bitfile *ld, int16_t *sp);
uint8_t huffman_2step_pair_sign(uint8_t cb, bitfile *ld, int16_t *sp);
uint8_t huffman_binary_quad(uint8_t cb, bitfile *ld, int16_t *sp);
uint8_t huffman_binary_quad_sign(uint8_t cb, bitfile *ld, int16_t *sp);
uint8_t huffman_binary_pair(uint8_t cb, bitfile *ld, int16_t *sp);
uint8_t huffman_binary_pair_sign(uint8_t cb, bitfile *ld, int16_t *sp);
int16_t huffman_codebook(uint8_t i);
void vcb11_check_LAV(uint8_t cb, int16_t *sp);
uint16_t drm_ps_data(drm_ps_info *ps, bitfile *ld);
drm_ps_info *drm_ps_init(void);
void drm_ps_free(drm_ps_info *ps);
uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, qmf_t X_left[38][64], qmf_t X_right[38][64]);
int8_t huffman_scale_factor(bitfile *ld);
uint8_t huffman_spectral_data(uint8_t cb, bitfile *ld, int16_t *sp);
int8_t huffman_spectral_data_2(uint8_t cb, bits_t *ld, int16_t *sp);
fb_info* ssr_filter_bank_init(uint16_t frame_len);
void ssr_filter_bank_end(fb_info* fb);
void ssr_ifilter_bank(fb_info* fb, uint8_t window_sequence, uint8_t window_shape, uint8_t window_shape_prev, real_t* freq_in, real_t* time_out, uint16_t frame_len);
int8_t AudioSpecificConfig2(uint8_t* pBuffer, uint32_t buffer_size, mp4AudioSpecificConfig* mp4ASC, program_config* pce, uint8_t short_form);
int8_t AudioSpecificConfigFromBitfile(bitfile* ld, mp4AudioSpecificConfig* mp4ASC, program_config* pce, uint32_t bsize, uint8_t short_form);
void pns_reset_pred_state(ic_stream* ics, pred_state* state);
void reset_all_predictors(pred_state* state, uint16_t frame_len);
void ic_prediction(ic_stream* ics, real_t* spec, pred_state* state, uint16_t frame_len, uint8_t sf_index);
uint8_t quant_to_spec(NeAACDecStruct* hDecoder, ic_stream* ics, int16_t* quant_data, real_t* spec_data, uint16_t frame_len);
uint8_t window_grouping_info(NeAACDecStruct* hDecoder, ic_stream* ics);
uint8_t reconstruct_channel_pair(NeAACDecStruct* hDecoder, ic_stream* ics1, ic_stream* ics2, element* cpe, int16_t* spec_data1, int16_t* spec_data2);
uint8_t reconstruct_single_channel(NeAACDecStruct* hDecoder, ic_stream* ics, element* sce, int16_t* spec_data);
void tns_decode_frame(ic_stream* ics, tns_info* tns, uint8_t sr_index, uint8_t object_type, real_t* spec, uint16_t frame_len);
void tns_encode_frame(ic_stream* ics, tns_info* tns, uint8_t sr_index, uint8_t object_type, real_t* spec, uint16_t frame_len);
uint8_t is_ltp_ot(uint8_t object_type);
void lt_prediction(ic_stream* ics, ltp_info* ltp, real_t* spec, int16_t* lt_pred_stat, fb_info* fb, uint8_t win_shape, uint8_t win_shape_prev, uint8_t sr_index, uint8_t object_type,
uint16_t frame_len);
void lt_update_state(int16_t* lt_pred_stat, real_t* time, real_t* overlap, uint16_t frame_len, uint8_t object_type);
void tns_decode_coef(uint8_t order, uint8_t coef_res_bits, uint8_t coef_compress, uint8_t* coef, real_t* a);
void tns_ar_filter(real_t* spectrum, uint16_t size, int8_t inc, real_t* lpc, uint8_t order);
void tns_ma_filter(real_t* spectrum, uint16_t size, int8_t inc, real_t* lpc, uint8_t order);
uint8_t faad_check_CRC(bitfile* ld, uint16_t len);
/* static function declarations */
void decode_sce_lfe(NeAACDecStruct* hDecoder, NeAACDecFrameInfo* hInfo, bitfile* ld, uint8_t id_syn_ele);
void decode_cpe(NeAACDecStruct* hDecoder, NeAACDecFrameInfo* hInfo, bitfile* ld, uint8_t id_syn_ele);
uint8_t single_lfe_channel_element(NeAACDecStruct* hDecoder, bitfile* ld, uint8_t channel, uint8_t* tag);
uint8_t channel_pair_element(NeAACDecStruct* hDecoder, bitfile* ld, uint8_t channel, uint8_t* tag);
#ifdef COUPLING_DEC
uint8_t coupling_channel_element(NeAACDecStruct* hDecoder, bitfile* ld);
#endif
uint16_t data_stream_element(NeAACDecStruct* hDecoder, bitfile* ld);
uint8_t program_config_element(program_config* pce, bitfile* ld);
uint8_t fill_element(NeAACDecStruct* hDecoder, bitfile* ld, drc_info* drc, uint8_t sbr_ele);
uint8_t individual_channel_stream(NeAACDecStruct* hDecoder, element* ele, bitfile* ld, ic_stream* ics, uint8_t scal_flag, int16_t* spec_data);
uint8_t ics_info(NeAACDecStruct* hDecoder, ic_stream* ics, bitfile* ld, uint8_t common_window);
uint8_t section_data(NeAACDecStruct* hDecoder, ic_stream* ics, bitfile* ld);
uint8_t scale_factor_data(NeAACDecStruct* hDecoder, ic_stream* ics, bitfile* ld);
#ifdef SSR_DEC
void gain_control_data(bitfile* ld, ic_stream* ics);
#endif
uint8_t spectral_data(NeAACDecStruct* hDecoder, ic_stream* ics, bitfile* ld, int16_t* spectral_data);
uint16_t extension_payload(bitfile* ld, drc_info* drc, uint16_t count);
uint8_t pulse_data(ic_stream* ics, pulse_info* pul, bitfile* ld);
void tns_data(ic_stream* ics, tns_info* tns, bitfile* ld);
#ifdef LTP_DEC
uint8_t ltp_data(NeAACDecStruct* hDecoder, ic_stream* ics, ltp_info* ltp, bitfile* ld);
#endif
uint8_t adts_fixed_header(adts_header* adts, bitfile* ld);
void adts_variable_header(adts_header* adts, bitfile* ld);
void adts_error_check(adts_header* adts, bitfile* ld);
uint8_t dynamic_range_info(bitfile* ld, drc_info* drc);
uint8_t excluded_channels(bitfile* ld, drc_info* drc);
uint8_t side_info(NeAACDecStruct* hDecoder, element* ele, bitfile* ld, ic_stream* ics, uint8_t scal_flag);
int8_t GASpecificConfig(bitfile* ld, mp4AudioSpecificConfig* mp4ASC, program_config* pce);
uint8_t adts_frame(adts_header* adts, bitfile* ld);
void get_adif_header(adif_header* adif, bitfile* ld);
void raw_data_block(NeAACDecStruct* hDecoder, NeAACDecFrameInfo* hInfo, bitfile* ld, program_config* pce, drc_info* drc);
uint8_t reordered_spectral_data(NeAACDecStruct* hDecoder, ic_stream* ics, bitfile* ld, int16_t* spectral_data);
#ifdef DRM
int8_t DRM_aac_scalable_main_header(NeAACDecStruct* hDecoder, ic_stream* ics1, ic_stream* ics2, bitfile* ld, uint8_t this_layer_stereo);
#endif
void dct4_kernel(real_t * in_real, real_t * in_imag, real_t * out_real, real_t * out_imag);
void DCT3_32_unscaled(real_t *y, real_t *x);
void DCT4_32(real_t *y, real_t *x);
void DST4_32(real_t *y, real_t *x);
void DCT2_32_unscaled(real_t *y, real_t *x);
void DCT4_16(real_t *y, real_t *x);
void DCT2_16_unscaled(real_t *y, real_t *x);
uint8_t rvlc_scale_factor_data(ic_stream *ics, bitfile *ld);
uint8_t rvlc_decode_scale_factors(ic_stream *ics, bitfile *ld);
uint8_t sbr_extension_data(bitfile* ld, sbr_info* sbr, uint16_t cnt, uint8_t resetFlag);
int8_t rvlc_huffman_sf(bitfile* ld_sf, bitfile* ld_esc, int8_t direction);
int8_t rvlc_huffman_esc(bitfile* ld_esc, int8_t direction);
uint8_t rvlc_decode_sf_forward(ic_stream* ics, bitfile* ld_sf, bitfile* ld_esc, uint8_t* intensity_used);
#ifdef DRM
void DRM_aac_scalable_main_element(NeAACDecStruct* hDecoder, NeAACDecFrameInfo* hInfo, bitfile* ld, program_config* pce, drc_info* drc);
#endif
uint32_t faad_latm_frame(latm_header *latm, bitfile *ld);
#ifdef SSR_DEC
void ssr_decode(ssr_info* ssr, fb_info* fb, uint8_t window_sequence, uint8_t window_shape, uint8_t window_shape_prev, real_t* freq_in, real_t* time_out, real_t* overlap,
real_t ipqf_buffer[SSR_BANDS][96 / 4], real_t* prev_fmd, uint16_t frame_len);
ssr_gain_control(ssr_info* ssr, real_t* data, real_t* output, real_t* overlap, real_t* prev_fmd, uint8_t band, uint8_t window_sequence, uint16_t frame_len);
ssr_gc_function(ssr_info* ssr, real_t* prev_fmd, real_t* gc_function, uint8_t window_sequence, uint16_t frame_len);
#endif
void extract_envelope_data(sbr_info *sbr, uint8_t ch);
void extract_noise_floor_data(sbr_info *sbr, uint8_t ch);
#ifndef FIXED_POINT
void envelope_noise_dequantisation(sbr_info *sbr, uint8_t ch);
void unmap_envelope_noise(sbr_info *sbr);
#endif
void ssr_ipqf(ssr_info* ssr, real_t* in_data, real_t* out_data, real_t buffer[SSR_BANDS][96 / 4], uint16_t frame_len, uint8_t bands);
mdct_info *faad_mdct_init(uint16_t N);
void faad_mdct_end(mdct_info *mdct);
void faad_imdct(mdct_info *mdct, real_t *X_in, real_t *X_out);
void faad_mdct(mdct_info *mdct, real_t *X_in, real_t *X_out);
#if (defined(PS_DEC) || defined(DRM_PS))
uint8_t sbrDecodeSingleFramePS(sbr_info* sbr, real_t* left_channel, real_t* right_channel, const uint8_t just_seeked, const uint8_t downSampledSBR);
#endif
void unmap_envelope_noise(sbr_info* sbr);
int16_t real_to_int16(real_t sig_in);
uint8_t sbr_save_prev_data(sbr_info* sbr, uint8_t ch);
void sbr_save_matrix(sbr_info* sbr, uint8_t ch);
fb_info *ssr_filter_bank_init(uint16_t frame_len);
void ssr_filter_bank_end(fb_info *fb);
void ssr_ifilter_bank(fb_info* fb, uint8_t window_sequence, uint8_t window_shape, uint8_t window_shape_prev, real_t* freq_in, real_t* time_out, uint16_t frame_len);
int32_t find_bands(uint8_t warp, uint8_t bands, uint8_t a0, uint8_t a1);
void sbr_header(bitfile* ld, sbr_info* sbr);
uint8_t calc_sbr_tables(sbr_info* sbr, uint8_t start_freq, uint8_t stop_freq, uint8_t samplerate_mode, uint8_t freq_scale, uint8_t alter_scale, uint8_t xover_band);
uint8_t sbr_data(bitfile* ld, sbr_info* sbr);
uint16_t sbr_extension(bitfile* ld, sbr_info* sbr, uint8_t bs_extension_id, uint16_t num_bits_left);
uint8_t sbr_single_channel_element(bitfile* ld, sbr_info* sbr);
uint8_t sbr_channel_pair_element(bitfile* ld, sbr_info* sbr);
uint8_t sbr_grid(bitfile* ld, sbr_info* sbr, uint8_t ch);
void sbr_dtdf(bitfile* ld, sbr_info* sbr, uint8_t ch);
void invf_mode(bitfile* ld, sbr_info* sbr, uint8_t ch);
void sinusoidal_coding(bitfile* ld, sbr_info* sbr, uint8_t ch);
uint8_t hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64], real_t *deg, uint8_t ch);
uint8_t qmf_start_channel(uint8_t bs_start_freq, uint8_t bs_samplerate_mode, uint32_t sample_rate);
uint8_t qmf_stop_channel(uint8_t bs_stop_freq, uint32_t sample_rate, uint8_t k0);
uint8_t master_frequency_table_fs0(sbr_info* sbr, uint8_t k0, uint8_t k2, uint8_t bs_alter_scale);
uint8_t master_frequency_table(sbr_info* sbr, uint8_t k0, uint8_t k2, uint8_t bs_freq_scale, uint8_t bs_alter_scale);
uint8_t derived_frequency_table(sbr_info* sbr, uint8_t bs_xover_band, uint8_t k2);
void limiter_frequency_table(sbr_info* sbr);
#ifdef SBR_DEC
#ifdef SBR_LOW_POWER
void calc_prediction_coef_lp(sbr_info* sbr, qmf_t Xlow[MAX_NTSRHFG][64], complex_t* alpha_0, complex_t* alpha_1, real_t* rxx);
void calc_aliasing_degree(sbr_info* sbr, real_t* rxx, real_t* deg);
#else // SBR_LOW_POWER
void calc_prediction_coef(sbr_info* sbr, qmf_t Xlow[MAX_NTSRHFG][64], complex_t* alpha_0, complex_t* alpha_1, uint8_t k);
#endif // SBR_LOW_POWER
void calc_chirp_factors(sbr_info* sbr, uint8_t ch);
void patch_construction(sbr_info* sbr);
#endif // SBR_DEC
#ifdef SBR_DEC
uint8_t estimate_current_envelope(sbr_info* sbr, sbr_hfadj_info* adj, qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
void calculate_gain(sbr_info* sbr, sbr_hfadj_info* adj, uint8_t ch);
#ifdef SBR_LOW_POWER
void calc_gain_groups(sbr_info* sbr, sbr_hfadj_info* adj, real_t* deg, uint8_t ch);
void aliasing_reduction(sbr_info* sbr, sbr_hfadj_info* adj, real_t* deg, uint8_t ch);
#endif // SBR_LOW_POWER
void hf_assembly(sbr_info* sbr, sbr_hfadj_info* adj, qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch);
#endif // SBR_DEC
uint8_t get_S_mapped(sbr_info* sbr, uint8_t ch, uint8_t l, uint8_t current_band);
qmfa_info* qmfa_init(uint8_t channels);
void qmfa_end(qmfa_info* qmfa);
qmfs_info* qmfs_init(uint8_t channels);
void qmfs_end(qmfs_info* qmfs);
void sbr_qmf_analysis_32(sbr_info* sbr, qmfa_info* qmfa, const real_t* input, qmf_t X[MAX_NTSRHFG][64], uint8_t offset, uint8_t kx);
void sbr_qmf_synthesis_32(sbr_info* sbr, qmfs_info* qmfs, qmf_t X[MAX_NTSRHFG][64], real_t* output);
void sbr_qmf_synthesis_64(sbr_info* sbr, qmfs_info* qmfs, qmf_t X[MAX_NTSRHFG][64], real_t* output);
uint8_t envelope_time_border_vector(sbr_info *sbr, uint8_t ch);
void noise_floor_time_border_vector(sbr_info *sbr, uint8_t ch);
void hf_generation(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], qmf_t Xhigh[MAX_NTSRHFG][64], real_t *deg, uint8_t ch);
void sbr_envelope(bitfile *ld, sbr_info *sbr, uint8_t ch);
void sbr_noise(bitfile *ld, sbr_info *sbr, uint8_t ch);
uint8_t middleBorder(sbr_info* sbr, uint8_t ch);
#ifdef SSR_DEC
static real_t **pp_q0, **pp_t0, **pp_t1;
void ssr_ipqf(ssr_info* ssr, real_t* in_data, real_t* out_data, real_t buffer[SSR_BANDS][96 / 4], uint16_t frame_len, uint8_t bands);
#endif

View File

@@ -0,0 +1,645 @@
/*
** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
** The "appropriate copyright message" mentioned in section 2c of the GPLv2
** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
**
** Commercial non-GPL licensing of this software is possible.
** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
**
** $Id: structs.h,v 1.49 2009/01/26 23:51:15 menno Exp $
**/
#pragma once
#include "neaacdec.h"
#define MAX_CHANNELS 64
#define MAX_SYNTAX_ELEMENTS 48
#define MAX_WINDOW_GROUPS 8
#define MAX_SFB 51
#define MAX_LTP_SFB 40
#define MAX_LTP_SFB_S 8
#define MAX_ASC_BYTES 64
/* used to save the prediction state */
typedef struct {
uint16_t n;
uint16_t ifac[15];
complex_t* work;
complex_t* tab;
} cfft_info;
typedef struct {
int16_t r[2];
int16_t COR[2];
int16_t VAR[2];
} pred_state;
typedef struct {
uint16_t N;
cfft_info* cfft;
complex_t* sincos;
int64_t cycles;
int64_t fft_cycles;
} mdct_info;
typedef struct {
const real_t* long_window[2];
const real_t* short_window[2];
const real_t* ld_window[2];
mdct_info* mdct256;
mdct_info* mdct1024;
mdct_info* mdct2048;
int64_t cycles;
} fb_info;
typedef struct {
uint8_t present;
uint8_t num_bands;
uint8_t pce_instance_tag;
uint8_t excluded_chns_present;
uint8_t band_top[17];
uint8_t prog_ref_level;
uint8_t dyn_rng_sgn[17];
uint8_t dyn_rng_ctl[17];
uint8_t exclude_mask[MAX_CHANNELS];
uint8_t additional_excluded_chns[MAX_CHANNELS];
real_t ctrl1;
real_t ctrl2;
} drc_info;
typedef struct {
uint8_t element_instance_tag;
uint8_t object_type;
uint8_t sf_index;
uint8_t num_front_channel_elements;
uint8_t num_side_channel_elements;
uint8_t num_back_channel_elements;
uint8_t num_lfe_channel_elements;
uint8_t num_assoc_data_elements;
uint8_t num_valid_cc_elements;
uint8_t mono_mixdown_present;
uint8_t mono_mixdown_element_number;
uint8_t stereo_mixdown_present;
uint8_t stereo_mixdown_element_number;
uint8_t matrix_mixdown_idx_present;
uint8_t pseudo_surround_enable;
uint8_t matrix_mixdown_idx;
uint8_t front_element_is_cpe[16];
uint8_t front_element_tag_select[16];
uint8_t side_element_is_cpe[16];
uint8_t side_element_tag_select[16];
uint8_t back_element_is_cpe[16];
uint8_t back_element_tag_select[16];
uint8_t lfe_element_tag_select[16];
uint8_t assoc_data_element_tag_select[16];
uint8_t cc_element_is_ind_sw[16];
uint8_t valid_cc_element_tag_select[16];
uint8_t channels;
uint8_t comment_field_bytes;
uint8_t comment_field_data[257];
uint8_t num_front_channels; /* extra added values */
uint8_t num_side_channels;
uint8_t num_back_channels;
uint8_t num_lfe_channels;
uint8_t sce_channel[16];
uint8_t cpe_channel[16];
} program_config;
typedef struct {
uint16_t syncword;
uint8_t id;
uint8_t layer;
uint8_t protection_absent;
uint8_t profile;
uint8_t sf_index;
uint8_t private_bit;
uint8_t channel_configuration;
uint8_t original;
uint8_t home;
uint8_t emphasis;
uint8_t copyright_identification_bit;
uint8_t copyright_identification_start;
uint16_t aac_frame_length;
uint16_t adts_buffer_fullness;
uint8_t no_raw_data_blocks_in_frame;
uint16_t crc_check;
uint8_t old_format;/* control param */
} adts_header;
typedef struct {
uint8_t copyright_id_present;
int8_t copyright_id[10];
uint8_t original_copy;
uint8_t home;
uint8_t bitstream_type;
uint32_t bitrate;
uint8_t num_program_config_elements;
uint32_t adif_buffer_fullness;
/* maximum of 16 PCEs */
program_config pce[16];
} adif_header;
typedef struct {
uint8_t last_band;
uint8_t data_present;
uint16_t lag;
uint8_t lag_update;
uint8_t coef;
uint8_t long_used[MAX_SFB];
uint8_t short_used[8];
uint8_t short_lag_present[8];
uint8_t short_lag[8];
} ltp_info;
typedef struct {
uint8_t limit;
uint8_t predictor_reset;
uint8_t predictor_reset_group_number;
uint8_t prediction_used[MAX_SFB];
} pred_info;
typedef struct {
uint8_t number_pulse;
uint8_t pulse_start_sfb;
uint8_t pulse_offset[4];
uint8_t pulse_amp[4];
} pulse_info;
typedef struct {
uint8_t n_filt[8];
uint8_t coef_res[8];
uint8_t length[8][4];
uint8_t order[8][4];
uint8_t direction[8][4];
uint8_t coef_compress[8][4];
uint8_t coef[8][4][32];
} tns_info;
typedef struct {
uint8_t max_band;
uint8_t adjust_num[4][8];
uint8_t alevcode[4][8][8];
uint8_t aloccode[4][8][8];
} ssr_info;
typedef struct {
uint8_t max_sfb;
uint8_t num_swb;
uint8_t num_window_groups;
uint8_t num_windows;
uint8_t window_sequence;
uint8_t window_group_length[8];
uint8_t window_shape;
uint8_t scale_factor_grouping;
uint16_t sect_sfb_offset[8][15 * 8];
uint16_t swb_offset[52];
uint16_t swb_offset_max;
uint8_t sect_cb[8][15 * 8];
uint16_t sect_start[8][15 * 8];
uint16_t sect_end[8][15 * 8];
uint8_t sfb_cb[8][8 * 15];
uint8_t num_sec[8]; /* number of sections in a group */
uint8_t global_gain;
int16_t scale_factors[8][51]; /* [0..255] */
uint8_t ms_mask_present;
uint8_t ms_used[MAX_WINDOW_GROUPS][MAX_SFB];
uint8_t noise_used;
uint8_t is_used;
uint8_t pulse_data_present;
uint8_t tns_data_present;
uint8_t gain_control_data_present;
uint8_t predictor_data_present;
pulse_info pul;
tns_info tns;
pred_info pred;
ltp_info ltp;
ltp_info ltp2;
ssr_info ssr;
uint16_t length_of_reordered_spectral_data; /* ER HCR data */
uint8_t length_of_longest_codeword;
uint8_t sf_concealment;/* ER RLVC data */
uint8_t rev_global_gain;
uint16_t length_of_rvlc_sf;
uint16_t dpcm_noise_nrg;
uint8_t sf_escapes_present;
uint8_t length_of_rvlc_escapes;
uint16_t dpcm_noise_last_position;
} ic_stream; /* individual channel stream */
typedef struct {
uint8_t channel;
int16_t paired_channel;
uint8_t element_instance_tag;
uint8_t common_window;
ic_stream ics1;
ic_stream ics2;
} element; /* syntax element (SCE, CPE, LFE) */
typedef struct {
int inited;
int version, versionA;
int framelen_type;
int useSameStreamMux;
int allStreamsSameTimeFraming;
int numSubFrames;
int numPrograms;
int numLayers;
int otherDataPresent;
uint32_t otherDataLenBits;
uint32_t frameLength;
uint8_t ASC[MAX_ASC_BYTES];
uint32_t ASCbits;
} latm_header;
typedef struct NeAACDecConfiguration
{
unsigned char defObjectType;
unsigned long defSampleRate;
unsigned char outputFormat;
unsigned char downMatrix;
unsigned char useOldADTSFormat;
unsigned char dontUpSampleImplicitSBR;
} NeAACDecConfiguration, *NeAACDecConfigurationPtr;
typedef struct
{
uint8_t drm_ps_data_available;
uint8_t bs_enable_sa;
uint8_t bs_enable_pan;
uint8_t bs_sa_dt_flag;
uint8_t bs_pan_dt_flag;
uint8_t g_last_had_sa;
uint8_t g_last_had_pan;
int8_t bs_sa_data[DRM_NUM_SA_BANDS];
int8_t bs_pan_data[DRM_NUM_PAN_BANDS];
int8_t g_sa_index[DRM_NUM_SA_BANDS];
int8_t g_pan_index[DRM_NUM_PAN_BANDS];
int8_t g_prev_sa_index[DRM_NUM_SA_BANDS];
int8_t g_prev_pan_index[DRM_NUM_PAN_BANDS];
int8_t sa_decode_error;
int8_t pan_decode_error;
int8_t g_last_good_sa_index[DRM_NUM_SA_BANDS];
int8_t g_last_good_pan_index[DRM_NUM_PAN_BANDS];
qmf_t SA[NUM_OF_SUBSAMPLES][MAX_SA_BAND];
complex_t d_buff[2][MAX_SA_BAND];
complex_t d2_buff[NUM_OF_LINKS][MAX_DELAY][MAX_SA_BAND];
uint8_t delay_buf_index_ser[NUM_OF_LINKS];
real_t prev_nrg[MAX_SA_BAND];
real_t prev_peakdiff[MAX_SA_BAND];
real_t peakdecay_fast[MAX_SA_BAND];
} drm_ps_info;
typedef struct
{
/* bitstream parameters */
uint8_t enable_iid;
uint8_t enable_icc;
uint8_t enable_ext;
uint8_t iid_mode;
uint8_t icc_mode;
uint8_t nr_iid_par;
uint8_t nr_ipdopd_par;
uint8_t nr_icc_par;
uint8_t frame_class;
uint8_t num_env;
uint8_t border_position[MAX_PS_ENVELOPES+1];
uint8_t iid_dt[MAX_PS_ENVELOPES];
uint8_t icc_dt[MAX_PS_ENVELOPES];
uint8_t enable_ipdopd;
uint8_t ipd_mode;
uint8_t ipd_dt[MAX_PS_ENVELOPES];
uint8_t opd_dt[MAX_PS_ENVELOPES];
/* indices */
int8_t iid_index_prev[34];
int8_t icc_index_prev[34];
int8_t ipd_index_prev[17];
int8_t opd_index_prev[17];
int8_t iid_index[MAX_PS_ENVELOPES][34];
int8_t icc_index[MAX_PS_ENVELOPES][34];
int8_t ipd_index[MAX_PS_ENVELOPES][17];
int8_t opd_index[MAX_PS_ENVELOPES][17];
int8_t ipd_index_1[17];
int8_t opd_index_1[17];
int8_t ipd_index_2[17];
int8_t opd_index_2[17];
/* ps data was correctly read */
uint8_t ps_data_available;
/* a header has been read */
uint8_t header_read;
/* hybrid filterbank parameters */
void *hyb;
uint8_t use34hybrid_bands;
uint8_t numTimeSlotsRate;
/**/
uint8_t num_groups;
uint8_t num_hybrid_groups;
uint8_t nr_par_bands;
uint8_t nr_allpass_bands;
uint8_t decay_cutoff;
uint8_t *group_border;
uint16_t *map_group2bk;
/* filter delay handling */
uint8_t saved_delay;
uint8_t delay_buf_index_ser[NO_ALLPASS_LINKS];
uint8_t num_sample_delay_ser[NO_ALLPASS_LINKS];
uint8_t delay_D[64];
uint8_t delay_buf_index_delay[64];
complex_t delay_Qmf[14][64]; /* 14 samples delay max, 64 QMF channels */
complex_t delay_SubQmf[2][32]; /* 2 samples delay max (SubQmf is always allpass filtered) */
complex_t delay_Qmf_ser[NO_ALLPASS_LINKS][5][64]; /* 5 samples delay max (table 8.34), 64 QMF channels */
complex_t delay_SubQmf_ser[NO_ALLPASS_LINKS][5][32]; /* 5 samples delay max (table 8.34) */
/* transients */
real_t alpha_decay;
real_t alpha_smooth;
real_t P_PeakDecayNrg[34];
real_t P_prev[34];
real_t P_SmoothPeakDecayDiffNrg_prev[34];
/* mixing and phase */
complex_t h11_prev[50];
complex_t h12_prev[50];
complex_t h21_prev[50];
complex_t h22_prev[50];
uint8_t phase_hist;
complex_t ipd_prev[20][2];
complex_t opd_prev[20][2];
} ps_info;
typedef struct {
real_t *x;
int16_t x_index;
uint8_t channels;
} qmfa_info;
typedef struct {
real_t *v;
int16_t v_index;
uint8_t channels;
} qmfs_info;
typedef struct{
uint32_t sample_rate;
uint32_t maxAACLine;
uint8_t rate;
uint8_t just_seeked;
uint8_t ret;
uint8_t amp_res[2];
uint8_t k0;
uint8_t kx;
uint8_t M;
uint8_t N_master;
uint8_t N_high;
uint8_t N_low;
uint8_t N_Q;
uint8_t N_L[4];
uint8_t n[2];
uint8_t f_master[64];
uint8_t f_table_res[2][64];
uint8_t f_table_noise[64];
uint8_t f_table_lim[4][64];
uint8_t f_group[5][64];
uint8_t N_G[5];
uint8_t table_map_k_to_g[64];
uint8_t abs_bord_lead[2];
uint8_t abs_bord_trail[2];
uint8_t n_rel_lead[2];
uint8_t n_rel_trail[2];
uint8_t L_E[2];
uint8_t L_E_prev[2];
uint8_t L_Q[2];
uint8_t t_E[2][MAX_L_E+1];
uint8_t t_Q[2][3];
uint8_t f[2][MAX_L_E+1];
uint8_t f_prev[2];
real_t *G_temp_prev[2][5];
real_t *Q_temp_prev[2][5];
int8_t GQ_ringbuf_index[2];
int16_t E[2][64][MAX_L_E];
int16_t E_prev[2][64];
real_t E_orig[2][64][MAX_L_E];
real_t E_curr[2][64][MAX_L_E];
int32_t Q[2][64][2];
real_t Q_div[2][64][2];
real_t Q_div2[2][64][2];
int32_t Q_prev[2][64];
int8_t l_A[2];
int8_t l_A_prev[2];
uint8_t bs_invf_mode[2][MAX_L_E];
uint8_t bs_invf_mode_prev[2][MAX_L_E];
real_t bwArray[2][64];
real_t bwArray_prev[2][64];
uint8_t noPatches;
uint8_t patchNoSubbands[64];
uint8_t patchStartSubband[64];
uint8_t bs_add_harmonic[2][64];
uint8_t bs_add_harmonic_prev[2][64];
uint16_t index_noise_prev[2];
uint8_t psi_is_prev[2];
uint8_t bs_start_freq_prev;
uint8_t bs_stop_freq_prev;
uint8_t bs_xover_band_prev;
uint8_t bs_freq_scale_prev;
uint8_t bs_alter_scale_prev;
uint8_t bs_noise_bands_prev;
int8_t prevEnvIsShort[2];
int8_t kx_prev;
uint8_t bsco;
uint8_t bsco_prev;
uint8_t M_prev;
uint16_t frame_len;
uint8_t Reset;
uint32_t frame;
uint32_t header_count;
uint8_t id_aac;
qmfa_info *qmfa[2];
qmfs_info *qmfs[2];
qmf_t Xsbr[2][MAX_NTSRHFG][64];
uint8_t Is_DRM_SBR;
drm_ps_info *drm_ps;
uint8_t numTimeSlotsRate;
uint8_t numTimeSlots;
uint8_t tHFGen;
uint8_t tHFAdj;
ps_info *ps;
uint8_t ps_used;
uint8_t psResetFlag;
/* to get it compiling */
/* we'll see during the coding of all the tools, whether
these are all used or not.
*/
uint8_t bs_header_flag;
uint8_t bs_crc_flag;
uint16_t bs_sbr_crc_bits;
uint8_t bs_protocol_version;
uint8_t bs_amp_res;
uint8_t bs_start_freq;
uint8_t bs_stop_freq;
uint8_t bs_xover_band;
uint8_t bs_freq_scale;
uint8_t bs_alter_scale;
uint8_t bs_noise_bands;
uint8_t bs_limiter_bands;
uint8_t bs_limiter_gains;
uint8_t bs_interpol_freq;
uint8_t bs_smoothing_mode;
uint8_t bs_samplerate_mode;
uint8_t bs_add_harmonic_flag[2];
uint8_t bs_add_harmonic_flag_prev[2];
uint8_t bs_extended_data;
uint8_t bs_extension_id;
uint8_t bs_extension_data;
uint8_t bs_coupling;
uint8_t bs_frame_class[2];
uint8_t bs_rel_bord[2][9];
uint8_t bs_rel_bord_0[2][9];
uint8_t bs_rel_bord_1[2][9];
uint8_t bs_pointer[2];
uint8_t bs_abs_bord_0[2];
uint8_t bs_abs_bord_1[2];
uint8_t bs_num_rel_0[2];
uint8_t bs_num_rel_1[2];
uint8_t bs_df_env[2][9];
uint8_t bs_df_noise[2][3];
} sbr_info;
typedef struct {
uint8_t adts_header_present;
uint8_t adif_header_present;
uint8_t latm_header_present;
uint8_t sf_index;
uint8_t object_type;
uint8_t channelConfiguration;
uint8_t aacSectionDataResilienceFlag;
uint8_t aacScalefactorDataResilienceFlag;
uint8_t aacSpectralDataResilienceFlag;
uint16_t frameLength;
uint8_t postSeekResetFlag;
uint32_t frame;
uint8_t downMatrix;
uint8_t upMatrix;
uint8_t first_syn_ele;
uint8_t has_lfe;
uint8_t fr_channels; /* number of channels in current frame */
uint8_t fr_ch_ele; /* number of elements in current frame */
uint8_t element_output_channels[MAX_SYNTAX_ELEMENTS]; /* element_output_channels: determines the number of channels the element will output */
uint8_t element_alloced[MAX_SYNTAX_ELEMENTS];/* element_alloced:determines whether the data needed for the element is allocated or not*/
uint8_t alloced_channels; /* alloced_channels: determines the number of channels where output data is allocated for*/
void* sample_buffer; /* output data buffer */
uint8_t window_shape_prev[MAX_CHANNELS];
uint16_t ltp_lag[MAX_CHANNELS];
fb_info* fb;
drc_info* drc;
real_t* time_out[MAX_CHANNELS];
real_t* fb_intermed[MAX_CHANNELS];
int8_t sbr_present_flag;
int8_t forceUpSampling;
int8_t downSampledSBR;
uint8_t sbr_alloced[MAX_SYNTAX_ELEMENTS]; /* determines whether SBR data is allocated for the gives element */
sbr_info* sbr[MAX_SYNTAX_ELEMENTS];
uint8_t ps_used[MAX_SYNTAX_ELEMENTS];
uint8_t ps_used_global;
real_t* ssr_overlap[MAX_CHANNELS];
real_t* prev_fmd[MAX_CHANNELS];
real_t ipqf_buffer[MAX_CHANNELS][4][96 / 4];
pred_state* pred_stat[MAX_CHANNELS];
int16_t* lt_pred_stat[MAX_CHANNELS];
uint8_t error_state;
uint32_t __r1; /* RNG states */
uint32_t __r2;
uint8_t pce_set;/* Program Config Element */
program_config pce;
uint8_t element_id[MAX_CHANNELS];
uint8_t internal_channel[MAX_CHANNELS];
NeAACDecConfiguration config; /* Configuration data */
int64_t cycles;
int64_t spectral_cycles;
int64_t output_cycles;
int64_t scalefac_cycles;
int64_t requant_cycles;
latm_header latm_config;
const unsigned char* cmes;
uint8_t isPS;
} NeAACDecStruct;
/* 1st step table */
typedef struct {
uint8_t offset;
uint8_t extra_bits;
} hcb;
/* 2nd step table with quadruple data */
typedef struct {
uint8_t bits;
int8_t x;
int8_t y;
} hcb_2_pair;
typedef struct {
uint8_t bits;
int8_t x;
int8_t y;
int8_t v;
int8_t w;
} hcb_2_quad;
/* binary search table */
typedef struct {
uint8_t is_leaf;
int8_t data[4];
} hcb_bin_quad;
typedef struct {
uint8_t is_leaf;
int8_t data[2];
} hcb_bin_pair;
typedef struct _bitfile {
/* bit input */
uint32_t bufa;
uint32_t bufb;
uint32_t bits_left;
uint32_t buffer_size; /* size of the buffer in bytes */
uint32_t bytes_left;
uint8_t error;
uint32_t* tail;
uint32_t* start;
const void* buffer;
} bitfile;
//——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#ifdef ERROR_RESILIENCE
/* Modified bit reading functions for HCR */
#endif /*ERROR_RESILIENCE*/
typedef struct {
/* bit input */
uint32_t bufa;
uint32_t bufb;
int8_t len;
} bits_t;
typedef struct {
uint8_t cb;
uint8_t decoded;
uint16_t sp_offset;
bits_t bits;
} codeword_t;
typedef struct
{
int8_t index;
uint8_t len;
uint32_t cw;
} rvlc_huff_table;
// ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#ifdef PS_DEC
/* type definitions */
typedef struct {
uint8_t frame_len;
uint8_t resolution20[3];
uint8_t resolution34[5];
qmf_t* work;
qmf_t** buffer;
qmf_t** temp;
} hyb_info;
#endif // PS_DEC
typedef struct {
real_t G_lim_boost[MAX_L_E][MAX_M];
real_t Q_M_lim_boost[MAX_L_E][MAX_M];
real_t S_M_boost[MAX_L_E][MAX_M];
} sbr_hfadj_info;
// ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
#ifdef SBR_DEC
typedef struct {
complex_t r01;
complex_t r02;
complex_t r11;
complex_t r12;
complex_t r22;
real_t det;
} acorr_coef;
#endif // SBR_DEC

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,515 @@
// based om helix mp3 decoder
#pragma once
#include "Arduino.h"
#include "assert.h"
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 {
ERR_MP3_NONE = 0,
ERR_MP3_INDATA_UNDERFLOW = -1,
ERR_MP3_MAINDATA_UNDERFLOW = -2,
ERR_MP3_FREE_BITRATE_SYNC = -3,
ERR_MP3_OUT_OF_MEMORY = -4,
ERR_MP3_NULL_POINTER = -5,
ERR_MP3_INVALID_FRAMEHEADER = -6,
ERR_MP3_INVALID_SIDEINFO = -7,
ERR_MP3_INVALID_SCALEFACT = -8,
ERR_MP3_INVALID_HUFFCODES = -9,
ERR_MP3_INVALID_DEQUANTIZE = -10,
ERR_MP3_INVALID_IMDCT = -11,
ERR_MP3_INVALID_SUBBAND = -12,
ERR_UNKNOWN = -9999
};
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;
/* 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()
*/
// prototypes
bool MP3Decoder_AllocateBuffers(void);
bool MP3Decoder_IsInit();
void MP3Decoder_FreeBuffers();
int32_t MP3Decode( uint8_t *inbuf, int32_t *bytesLeft, int16_t *outbuf, int32_t useSize);
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();
int32_t MP3GetLayer();
int32_t MP3GetVersion();
//internally used
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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,314 @@
#pragma once
//#pragma GCC optimize ("O3")
//#pragma GCC diagnostic ignored "-Wnarrowing"
/********************************************************************
* *
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
* by the Xiph.Org Foundation https://xiph.org/ *
* *
********************************************************************/
/*
* vorbis_decoder.h
* based on Xiph.Org Foundation vorbis decoder
* adapted for the ESP32 by schreibfaul1
*
* Created on: 13.02.2023
* Updated on: 03.04.2024
*/
#include "Arduino.h"
#include <vector>
using namespace std;
#define VI_FLOORB 2
#define VIF_POSIT 63
#define LSP_FRACBITS 14
#define OV_EREAD -128
#define OV_EFAULT -129
#define OV_EIMPL -130
#define OV_EINVAL -131
#define OV_ENOTVORBIS -132
#define OV_EBADHEADER -133
#define OV_EVERSION -134
#define OV_ENOTAUDIO -135
#define OV_EBADPACKET -136
#define OV_EBADLINK -137
#define OV_ENOSEEK -138
#define INVSQ_LOOKUP_I_SHIFT 10
#define INVSQ_LOOKUP_I_MASK 1023
#define COS_LOOKUP_I_SHIFT 9
#define COS_LOOKUP_I_MASK 511
#define COS_LOOKUP_I_SZ 128
#define cPI3_8 (0x30fbc54d)
#define cPI2_8 (0x5a82799a)
#define cPI1_8 (0x7641af3d)
enum : int8_t {VORBIS_CONTINUE = 110,
VORBIS_PARSE_OGG_DONE = 100,
ERR_VORBIS_NONE = 0,
ERR_VORBIS_CHANNELS_OUT_OF_RANGE = -1,
ERR_VORBIS_INVALID_SAMPLERATE = -2,
ERR_VORBIS_EXTRA_CHANNELS_UNSUPPORTED = -3,
ERR_VORBIS_DECODER_ASYNC = -4,
ERR_VORBIS_OGG_SYNC_NOT_FOUND = - 5,
ERR_VORBIS_BAD_HEADER = -6,
ERR_VORBIS_NOT_AUDIO = -7,
ERR_VORBIS_BAD_PACKET = -8
};
typedef struct _codebook{
uint8_t dim; /* codebook dimensions (elements per vector) */
int16_t entries; /* codebook entries */
uint16_t used_entries; /* populated codebook entries */
uint32_t dec_maxlength;
void *dec_table;
uint32_t dec_nodeb;
uint32_t dec_leafw;
uint32_t dec_type; /* 0 = entry number
1 = packed vector of values
2 = packed vector of column offsets, maptype 1
3 = scalar offset into value array, maptype 2 */
int32_t q_min;
int32_t q_minp;
int32_t q_del;
int32_t q_delp;
int32_t q_seq;
int32_t q_bits;
uint8_t q_pack;
void *q_val;
} codebook_t;
typedef struct{
char class_dim; /* 1 to 8 */
char class_subs; /* 0,1,2,3 (bits: 1<<n poss) */
uint8_t class_book; /* subs ^ dim entries */
uint8_t class_subbook[8]; /* [VIF_CLASS][subs] */
} floor1class_t;
typedef struct{
int32_t order;
int32_t rate;
int32_t barkmap;
int32_t ampbits;
int32_t ampdB;
int32_t numbooks; /* <= 16 */
char books[16];
floor1class_t *_class; /* [VIF_CLASS] */
uint8_t *partitionclass; /* [VIF_PARTS]; 0 to 15 */
uint16_t *postlist; /* [VIF_POSIT+2]; first two implicit */
uint8_t *forward_index; /* [VIF_POSIT+2]; */
uint8_t *hineighbor; /* [VIF_POSIT]; */
uint8_t *loneighbor; /* [VIF_POSIT]; */
int32_t partitions; /* 0 to 31 */
int32_t posts;
int32_t mult; /* 1 2 3 or 4 */
} vorbis_info_floor_t;
typedef struct _vorbis_info_residue {
int32_t type;
uint8_t *stagemasks;
uint8_t *stagebooks;
/* block-partitioned VQ coded straight residue */
uint32_t begin;
uint32_t end;
/* first stage (lossless partitioning) */
uint32_t grouping; /* group n vectors per partition */
char partitions; /* possible codebooks for a partition */
uint8_t groupbook; /* huffbook for partitioning */
char stages;
} vorbis_info_residue_t;
typedef struct _submap{
char floor;
char residue;
} submap_t;
typedef struct _coupling_step{ // Mapping backend generic
uint8_t mag;
uint8_t ang;
} coupling_step_t;
typedef struct _vorbis_info_mapping{
int32_t submaps;
uint8_t *chmuxlist;
submap_t *submaplist;
int32_t coupling_steps;
coupling_step_t *coupling;
} vorbis_info_mapping_t;
typedef struct { // mode
uint8_t blockflag;
uint8_t mapping;
} vorbis_info_mode_t;
typedef struct _vorbis_dsp_state{ // vorbis_dsp_state buffers the current vorbis audio analysis/synthesis state.
// vorbis_info *vi; // The DSP state be int32_ts to a specific logical bitstream
// oggpack_buffer_t opb;
int32_t **work;
int32_t **mdctright;
int32_t out_begin;
int32_t out_end;
int32_t lW; // last window
uint32_t W; // Window
} vorbis_dsp_state_t;
typedef struct _bitreader{
uint8_t *data;
uint8_t length;
uint16_t headbit;
uint8_t *headptr;
int32_t headend;
} bitReader_t;
//----------------------------------------------------------------------------------------------------------------------
union magic{
struct{
int32_t lo;
int32_t hi;
} halves;
int64_t whole;
};
inline int32_t MULT32(int32_t x, int32_t y) {
union magic magic;
magic.whole = (int64_t)x * y;
return magic.halves.hi;
}
inline int32_t MULT31_SHIFT15(int32_t x, int32_t y) {
union magic magic;
magic.whole = (int64_t)x * y;
return ((uint32_t)(magic.halves.lo) >> 15) | ((magic.halves.hi) << 17);
}
inline int32_t MULT31(int32_t x, int32_t y) { return MULT32(x, y) << 1; }
inline void XPROD31(int32_t a, int32_t b, int32_t t, int32_t v, int32_t *x, int32_t *y) {
*x = MULT31(a, t) + MULT31(b, v);
*y = MULT31(b, t) - MULT31(a, v);
}
inline void XNPROD31(int32_t a, int32_t b, int32_t t, int32_t v, int32_t *x, int32_t *y) {
*x = MULT31(a, t) - MULT31(b, v);
*y = MULT31(b, t) + MULT31(a, v);
}
inline int32_t CLIP_TO_15(int32_t x) {
int32_t ret = x;
ret -= ((x <= 32767) - 1) & (x - 32767);
ret -= ((x >= -32768) - 1) & (x + 32768);
return (ret);
}
//----------------------------------------------------------------------------------------------------------------------
// ogg impl
bool VORBISDecoder_AllocateBuffers();
void VORBISDecoder_FreeBuffers();
void VORBISDecoder_ClearBuffers();
void VORBISsetDefaults();
void clearGlobalConfigurations();
int32_t VORBISDecode(uint8_t* inbuf, int32_t* bytesLeft, int16_t* outbuf);
uint8_t VORBISGetChannels();
uint32_t VORBISGetSampRate();
uint32_t VORBISGetAudioDataStart();
uint8_t VORBISGetBitsPerSample();
uint32_t VORBISGetBitRate();
uint16_t VORBISGetOutputSamps();
char* VORBISgetStreamTitle();
vector<uint32_t> VORBISgetMetadataBlockPicture();
int32_t VORBISFindSyncWord(unsigned char* buf, int32_t nBytes);
int32_t VORBISparseOGG(uint8_t* inbuf, int32_t* bytesLeft);
int32_t vorbisDecodePage1(uint8_t* inbuf, int32_t* bytesLeft, uint32_t segmentLength);
int32_t vorbisDecodePage2(uint8_t* inbuf, int32_t* bytesLeft, uint32_t segmentLength);
int32_t vorbisDecodePage3(uint8_t* inbuf, int32_t* bytesLeft, uint32_t segmentLength);
int32_t vorbisDecodePage4(uint8_t* inbuf, int32_t* bytesLeft, uint32_t segmentLength, int16_t* outbuf);
int32_t parseVorbisComment(uint8_t* inbuf, int16_t nBytes);
int32_t parseVorbisCodebook();
int32_t parseVorbisFirstPacket(uint8_t* inbuf, int16_t nBytes);
uint16_t continuedOggPackets(uint8_t* inbuf);
int32_t vorbis_book_unpack(codebook_t* s);
uint32_t decpack(int32_t entry, int32_t used_entry, uint8_t quantvals, codebook_t* b, int32_t maptype);
int32_t oggpack_eop();
vorbis_info_floor_t* floor0_info_unpack();
vorbis_info_floor_t* floor1_info_unpack();
int32_t res_unpack(vorbis_info_residue_t* info);
int32_t mapping_info_unpack(vorbis_info_mapping_t* info);
void vorbis_mergesort(uint8_t* index, uint16_t* vals, uint16_t n);
void floor_free_info(vorbis_info_floor_t* i);
void res_clear_info(vorbis_info_residue_t* info);
void mapping_clear_info(vorbis_info_mapping_t* info);
// vorbis decoder impl
int32_t vorbis_dsp_synthesis(uint8_t* inbuf, uint16_t len, int16_t* outbuf);
vorbis_dsp_state_t* vorbis_dsp_create();
void vorbis_dsp_destroy(vorbis_dsp_state_t* v);
void mdct_shift_right(int32_t n, int32_t* in, int32_t* right);
int32_t mapping_inverse(vorbis_info_mapping_t* info);
int32_t floor0_memosize(vorbis_info_floor_t* i);
int32_t floor1_memosize(vorbis_info_floor_t* i);
int32_t* floor0_inverse1(vorbis_info_floor_t* i, int32_t* lsp);
int32_t* floor1_inverse1(vorbis_info_floor_t* in, int32_t* fit_value);
int32_t vorbis_book_decode(codebook_t* book);
int32_t decode_packed_entry_number(codebook_t* book);
int32_t render_point(int32_t x0, int32_t x1, int32_t y0, int32_t y1, int32_t x);
int32_t vorbis_book_decodev_set(codebook_t* book, int32_t* a, int32_t n, int32_t point);
int32_t decode_map(codebook_t* s, int32_t* v, int32_t point);
int32_t res_inverse(vorbis_info_residue_t* info, int32_t** in, int32_t* nonzero, uint8_t ch);
int32_t vorbis_book_decodev_add(codebook_t* book, int32_t* a, int32_t n, int32_t point);
int32_t vorbis_book_decodevs_add(codebook_t* book, int32_t* a, int32_t n, int32_t point);
int32_t floor0_inverse2(vorbis_info_floor_t* i, int32_t* lsp, int32_t* out);
int32_t floor1_inverse2(vorbis_info_floor_t* in, int32_t* fit_value, int32_t* out);
void render_line(int32_t n, int32_t x0, int32_t x1, int32_t y0, int32_t y1, int32_t* d);
void vorbis_lsp_to_curve(int32_t* curve, int32_t n, int32_t ln, int32_t* lsp, int32_t m, int32_t amp, int32_t ampoffset, int32_t nyq);
int32_t toBARK(int32_t n);
int32_t vorbis_coslook_i(int32_t a);
int32_t vorbis_coslook2_i(int32_t a);
int32_t vorbis_fromdBlook_i(int32_t a);
int32_t vorbis_invsqlook_i(int32_t a, int32_t e);
void mdct_backward(int32_t n, int32_t* in);
void presymmetry(int32_t* in, int32_t n2, int32_t step);
void mdct_butterflies(int32_t* x, int32_t points, int32_t shift);
void mdct_butterfly_generic(int32_t* x, int32_t points, int32_t step);
void mdct_butterfly_32(int32_t* x);
void mdct_butterfly_16(int32_t* x);
void mdct_butterfly_8(int32_t* x);
void mdct_bitreverse(int32_t* x, int32_t n, int32_t shift);
int32_t bitrev12(int32_t x);
void mdct_step7(int32_t* x, int32_t n, int32_t step);
void mdct_step8(int32_t* x, int32_t n, int32_t step);
int32_t vorbis_book_decodevv_add(codebook_t* book, int32_t** a, int32_t offset, uint8_t ch, int32_t n, int32_t point);
int32_t vorbis_dsp_pcmout(int16_t* outBuff, int32_t outBuffSize);
void mdct_unroll_lap(int32_t n0, int32_t n1, int32_t lW, int32_t W, int32_t* in, int32_t* right, const int32_t* w0, const int32_t* w1, int16_t* out, int32_t step, int32_t start, /* samples, this frame */
int32_t end /* samples, this frame */);
// some helper functions
int32_t VORBIS_specialIndexOf(uint8_t* base, const char* str, int32_t baselen, bool exact = false);
void bitReader_clear();
void bitReader_setData(uint8_t *buff, uint16_t buffSize);
int32_t bitReader(uint16_t bits);
int32_t bitReader_look(uint16_t nBits);
int8_t bitReader_adv(uint16_t bits);
uint8_t _ilog(uint32_t v);
int32_t ilog(uint32_t v);
int32_t _float32_unpack(int32_t val, int32_t *point);
int32_t _determine_node_bytes(uint32_t used, uint8_t leafwidth);
int32_t _determine_leaf_words(int32_t nodeb, int32_t leafwidth);
int32_t _make_decode_table(codebook_t *s, char *lengthlist, uint8_t quantvals, int32_t maptype);
int32_t _make_words(char *l, uint16_t n, uint32_t *r, uint8_t quantvals, codebook_t *b, int32_t maptype);
uint8_t _book_maptype1_quantvals(codebook_t *b);
void vorbis_book_clear(codebook_t *b);
int32_t *_vorbis_window(int32_t left);