removed codecs to save memory
This commit is contained in:
6189
lib/ESP32-audioI2S/src/Audio.cpp
Normal file
6189
lib/ESP32-audioI2S/src/Audio.cpp
Normal file
File diff suppressed because it is too large
Load Diff
763
lib/ESP32-audioI2S/src/Audio.h
Normal file
763
lib/ESP32-audioI2S/src/Audio.h
Normal 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;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
189
lib/ESP32-audioI2S/src/aac_decoder/aac_decoder.cpp
Normal file
189
lib/ESP32-audioI2S/src/aac_decoder/aac_decoder.cpp
Normal 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));
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
34
lib/ESP32-audioI2S/src/aac_decoder/aac_decoder.h
Normal file
34
lib/ESP32-audioI2S/src/aac_decoder/aac_decoder.h
Normal 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);
|
||||
15903
lib/ESP32-audioI2S/src/aac_decoder/libfaad/neaacdec.cpp
Normal file
15903
lib/ESP32-audioI2S/src/aac_decoder/libfaad/neaacdec.cpp
Normal file
File diff suppressed because it is too large
Load Diff
859
lib/ESP32-audioI2S/src/aac_decoder/libfaad/neaacdec.h
Normal file
859
lib/ESP32-audioI2S/src/aac_decoder/libfaad/neaacdec.h
Normal 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
|
||||
645
lib/ESP32-audioI2S/src/aac_decoder/libfaad/structs.h
Normal file
645
lib/ESP32-audioI2S/src/aac_decoder/libfaad/structs.h
Normal 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
|
||||
24341
lib/ESP32-audioI2S/src/aac_decoder/libfaad/tables.h
Normal file
24341
lib/ESP32-audioI2S/src/aac_decoder/libfaad/tables.h
Normal file
File diff suppressed because it is too large
Load Diff
3868
lib/ESP32-audioI2S/src/mp3_decoder/mp3_decoder.cpp
Normal file
3868
lib/ESP32-audioI2S/src/mp3_decoder/mp3_decoder.cpp
Normal file
File diff suppressed because it is too large
Load Diff
515
lib/ESP32-audioI2S/src/mp3_decoder/mp3_decoder.h
Normal file
515
lib/ESP32-audioI2S/src/mp3_decoder/mp3_decoder.h
Normal 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
|
||||
1236
lib/ESP32-audioI2S/src/vorbis_decoder/lookup.h
Normal file
1236
lib/ESP32-audioI2S/src/vorbis_decoder/lookup.h
Normal file
File diff suppressed because it is too large
Load Diff
3293
lib/ESP32-audioI2S/src/vorbis_decoder/vorbis_decoder.cpp
Normal file
3293
lib/ESP32-audioI2S/src/vorbis_decoder/vorbis_decoder.cpp
Normal file
File diff suppressed because it is too large
Load Diff
314
lib/ESP32-audioI2S/src/vorbis_decoder/vorbis_decoder.h
Normal file
314
lib/ESP32-audioI2S/src/vorbis_decoder/vorbis_decoder.h
Normal 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);
|
||||
Reference in New Issue
Block a user