code upload

This commit is contained in:
e2002
2022-02-04 17:30:12 +03:00
parent fe3f0a261e
commit 3565d2fa17
44 changed files with 25103 additions and 1 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,480 @@
/*
* Audio.h
*
* Created on: Oct 26,2018
* Updated on: Jan 05,2022
* Author: Wolle (schreibfaul1)
*/
//#define SDFATFS_USED // activate for SdFat
#pragma once
#pragma GCC optimize ("Ofast")
#include <Arduino.h>
#include <libb64/cencode.h>
#include <SPI.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <driver/i2s.h>
#ifdef SDFATFS_USED
#include <SdFat.h> // https://github.com/greiman/SdFat
#else
#include <SD.h>
#include <SD_MMC.h>
#include <SPIFFS.h>
#include <FS.h>
#include <FFat.h>
#endif // SDFATFS_USED
#define AUDIOBUFFER_MULTIPLIER 13
#ifdef SDFATFS_USED
typedef File32 File;
namespace fs {
class FS : public SdFat {
public:
bool begin(SdCsPin_t csPin = SS, uint32_t maxSck = SD_SCK_MHZ(25)) { return SdFat::begin(csPin, maxSck); }
};
class SDFATFS : public fs::FS {
public:
// sdcard_type_t cardType();
uint64_t cardSize() {
return totalBytes();
}
uint64_t usedBytes() {
// set SdFatConfig MAINTAIN_FREE_CLUSTER_COUNT non-zero. Then only the first call will take time.
return (uint64_t)(clusterCount() - freeClusterCount()) * (uint64_t)bytesPerCluster();
}
uint64_t totalBytes() {
return (uint64_t)clusterCount() * (uint64_t)bytesPerCluster();
}
};
}
extern fs::SDFATFS SD_SDFAT;
using namespace fs;
#define SD SD_SDFAT
#endif //SDFATFS_USED
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_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_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_extern(int16_t* buff, uint16_t len, bool *continueI2S); // record audiodata or send via BT
//----------------------------------------------------------------------------------------------------------------------
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
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
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
protected:
const size_t m_buffSizePSRAM = 300000; // most webstreams limit the advance to 100...300Kbytes
//const size_t m_buffSizeRAM = 1600 * 5 * AUDIOBUFFER_MULTIPLIER;
const size_t m_buffSizeRAM = 1600 * AUDIOBUFFER_MULTIPLIER;
size_t m_buffSize = 0;
size_t m_freeSpace = 0;
size_t m_writeSpace = 0;
size_t m_dataLength = 0;
//size_t m_resBuffSizeRAM = 1600 * AUDIOBUFFER_MULTIPLIER; // reserved buffspace, >= one mp3 frame
size_t m_resBuffSizeRAM = 1600; // reserved buffspace, >= one mp3 frame
size_t m_resBuffSizePSRAM = 4096 * 4; // 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_start = true;
};
//----------------------------------------------------------------------------------------------------------------------
class Audio : private AudioBuffer{
AudioBuffer InBuff; // instance of input buffer
public:
Audio(bool internalDAC = false, i2s_dac_mode_t channelEnabled = I2S_DAC_CHANNEL_LEFT_EN); // #99
~Audio();
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);
bool connecttoSD(const char* path);
bool setFileLoop(bool input);//TEST loop
bool setAudioPlayPosition(uint16_t sec);
bool setFilePos(uint32_t pos);
bool audioFileSeek(const float speed);
bool setTimeOffset(int sec);
bool setPinout(uint8_t BCLK, uint8_t LRC, uint8_t DOUT, int8_t DIN=I2S_PIN_NO_CHANGE);
bool pauseResume();
bool isRunning() {return m_f_running;}
void loop();
void stopSong();
void forceMono(bool m);
void setBalance(int8_t bal = 0);
void setVolume(uint8_t vol);
uint8_t getVolume();
uint32_t getAudioDataStartPos();
uint32_t getFileSize();
uint32_t getFilePos();
uint32_t getSampleRate();
uint8_t getBitsPerSample();
uint8_t getChannels();
uint32_t getBitRate();
uint32_t getAudioFileDuration();
uint32_t getAudioCurrentTime();
uint32_t getTotalPlayingTime();
esp_err_t i2s_mclk_pin_select(const uint8_t pin);
uint32_t inBufferFilled(); // returns the number of stored bytes in the inputbuffer
uint32_t inBufferFree(); // returns the number of free bytes in the inputbuffer
void setTone(int8_t gainLowPass, int8_t gainBandPass, int8_t gainHighPass);
[[deprecated]]void setInternalDAC(bool internalDAC = true, i2s_dac_mode_t channelEnabled = I2S_DAC_CHANNEL_LEFT_EN);
void setI2SCommFMT_LSB(bool commFMT);
private:
void UTF8toASCII(char* str);
bool latinToUTF8(char* buff, size_t bufflen);
void httpPrint(const char* url);
void setDefaults(); // free buffers and set defaults
void initInBuff();
void processLocalFile();
void processWebStream();
void processPlayListData();
void processM3U8entries(uint8_t nrOfEntries = 0, uint32_t seqNr = 0, uint8_t pos = 0, uint16_t targetDuration = 0);
bool STfromEXTINF(char* str);
void showCodecParams();
int findNextSync(uint8_t* data, size_t len);
int sendBytes(uint8_t* data, size_t len);
void compute_audioCurrentTime(int bd);
void printDecodeError(int r);
void showID3Tag(const char* tag, const char* val);
void unicode2utf8(char* buff, uint32_t len);
int read_WAV_Header(uint8_t* data, size_t len);
int read_FLAC_Header(uint8_t *data, size_t len);
int read_MP3_Header(uint8_t* data, size_t len);
int read_M4A_Header(uint8_t* data, size_t len);
int read_OGG_Header(uint8_t *data, size_t len);
bool setSampleRate(uint32_t hz);
bool setBitsPerSample(int bits);
bool setChannels(int channels);
bool setBitrate(int br);
bool playChunk();
bool playSample(int16_t sample[2]) ;
bool playI2Sremains();
int32_t Gain(int16_t s[2]);
bool fill_InputBuf();
void showstreamtitle(const char* ml);
bool parseContentType(const char* ct);
void processAudioHeaderData();
bool readMetadata(uint8_t b, bool first = false);
esp_err_t I2Sstart(uint8_t i2s_num);
esp_err_t I2Sstop(uint8_t i2s_num);
void urlencode(char* buff, uint16_t buffLen, bool spacesOnly = false);
int16_t* IIR_filterChain0(int16_t iir_in[2], bool clear = false);
int16_t* IIR_filterChain1(int16_t* iir_in, bool clear = false);
int16_t* IIR_filterChain2(int16_t* iir_in, bool clear = false);
inline void setDatamode(uint8_t dm){m_datamode=dm;}
inline uint8_t getDatamode(){return m_datamode;}
inline uint32_t streamavail() {if(m_f_ssl==false) return client.available(); else return clientsecure.available();}
void IIR_calculateCoefficients(int8_t G1, int8_t G2, int8_t G3);
// implement several function with respect to the index of string
void trim(char *s) {
//fb trim in place
char *pe;
char *p = s;
while ( isspace(*p) ) p++; //left
pe = p; //right
while ( *pe != '\0' ) pe++;
do {
pe--;
} while ( (pe > p) && isspace(*pe) );
if (p == s) {
*++pe = '\0';
} else { //move
while ( p <= pe ) *s++ = *p++;
*s = '\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* str) {
//fb
int slen = strlen(str) - 1;
const char *p = base + strlen(base) - 1;
while(p > base && isspace(*p)) p--; // rtrim
p -= slen;
if (p < base) return false;
return (strncmp(p, str, slen) == 0);
}
int indexOf (const char* base, const char* str, int startIndex) {
//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) {
//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; // 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;
}
size_t bigEndian(uint8_t* base, uint8_t numBytes, uint8_t shiftLeft = 8){
size_t result = 0;
if(numBytes < 1 or numBytes > 4) return 0;
for (int i = 0; i < numBytes; i++) {
result += *(base + i) << (numBytes -i - 1) * shiftLeft;
}
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);
len = base64_encode_blockend((buffer + len), &_state);
memcpy(dest, buffer, strlen(buffer));
dest[strlen(buffer)] = '\0';
free(buffer);
return true;
}
return false;
}
size_t urlencode_expected_len(const char* source){
size_t expectedLen = strlen(source);
for(int i = 0; i < strlen(source); i++) {
if(isalnum(source[i])){;}
else expectedLen += 2;
}
return expectedLen;
}
private:
enum : int { APLL_AUTO = -1, APLL_ENABLE = 1, APLL_DISABLE = 0 };
enum : int { EXTERNAL_I2S = 0, INTERNAL_DAC = 1, INTERNAL_PDM = 2 };
enum : int { CODEC_NONE, CODEC_WAV, CODEC_MP3, CODEC_AAC, CODEC_M4A, CODEC_FLAC, CODEC_OGG,
CODEC_OGG_FLAC, CODEC_OGG_OPUS};
enum : int { FORMAT_NONE = 0, FORMAT_M3U = 1, FORMAT_PLS = 2, FORMAT_ASX = 3, FORMAT_M3U8 = 4};
enum : int { AUDIO_NONE, AUDIO_HEADER, AUDIO_DATA,
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 { OGG_BEGIN = 0, OGG_MAGIC = 1, OGG_HEADER = 2, OGG_FIRST = 3, OGG_AMRDY = 99, OGG_OKAY = 100};
typedef enum { LEFTCHANNEL=0, RIGHTCHANNEL=1 } SampleIndex;
typedef enum { LOWSHELF = 0, PEAKEQ = 1, HIFGSHELF =2 } FilterType;
const uint8_t volumetable[22]={ 0, 1, 2, 3, 4 , 6 , 8, 10, 12, 14, 17,
20, 23, 27, 30 ,34, 38, 43 ,48, 52, 58, 64}; //22 elements
typedef struct _filter{
float a0;
float a1;
float a2;
float b1;
float b2;
} filter_t;
File audiofile; // @suppress("Abstract class cannot be instantiated")
WiFiClient client; // @suppress("Abstract class cannot be instantiated")
WiFiClientSecure clientsecure; // @suppress("Abstract class cannot be instantiated")
WiFiUDP udpclient; // @suppress("Abstract class cannot be instantiated")
i2s_config_t m_i2s_config; // stores values for I2S driver
i2s_pin_config_t m_pin_config;
const size_t m_frameSizeWav = 1600;
const size_t m_frameSizeMP3 = 1600;
const size_t m_frameSizeAAC = 1600;
const size_t m_frameSizeFLAC = 4096 * 4;
char chbuf[512 + 128]; // must be greater than m_lastHost #254
char m_lastHost[512]; // Store the last URL to a webstream
char* m_playlistBuff = NULL; // stores playlistdata
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
int m_metalen=0; // Number of bytes in metadata
int m_controlCounter = 0; // Status within readID3data() and readWaveHeader()
int8_t m_balance = 0; // -16 (mute left) ... +16 (mute right)
uint8_t m_vol=64; // volume
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_m3u8codec = CODEC_NONE; // M4A
uint8_t m_codec = CODEC_NONE; //
uint8_t m_filterType[2]; // lowpass, highpass
int16_t m_outBuff[2048*2]; // Interleaved L/R
int16_t m_validSamples = 0;
int16_t m_curSample = 0;
uint16_t m_st_remember = 0; // Save hash from the last streamtitle
uint16_t m_datamode = 0; // Statemaschine
uint8_t m_flacBitsPerSample = 0; // bps should be 16
uint8_t m_flacNumChannels = 0; // can be read out in the FLAC file header
uint32_t m_flacSampleRate = 0; // can be read out in the FLAC file header
uint16_t m_flacMaxFrameSize = 0; // can be read out in the FLAC file header
uint16_t m_flacMaxBlockSize = 0; // can be read out in the FLAC file header
uint32_t m_flacTotalSamplesInStream = 0; // can be read out in the FLAC file header
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
bool m_f_swm = true; // 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_localfile = false ; // Play from local mp3-file
bool m_f_webstream = false ; // Play from URL
bool m_f_ssl = false;
bool m_f_running = false;
bool m_f_firstCall = false; // InitSequence for processWebstream and processLokalFile
bool m_f_ctseen = false; // First line of header seen or not
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_webfile = false; // assume it's a radiostream, not a podcast
bool m_f_tts = false; // text to speech
bool m_f_psram = false; // set if PSRAM is availabe
bool m_f_loop = false; // Set if audio file should loop
bool m_f_forceMono = false; // if true stereo -> mono
bool m_f_internalDAC = false; // false: output vis I2S, true output via internal DAC
bool m_f_rtsp = false; // set if RTSP is used (m3u8 stream)
bool m_f_m3u8data = false; // used in processM3U8entries
bool m_f_Log = true; // if m3u8: log is cancelled
bool m_f_continue = false; // next m3u8 chunk is available
bool m_f_initInbuffOnce = false; // init InBuff only once
i2s_dac_mode_t m_f_channelEnabled = I2S_DAC_CHANNEL_LEFT_EN; // internal DAC on GPIO26 for M5StickC/Plus
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
size_t m_i2s_bytesWritten = 0; // set in i2s_write() but not used
size_t m_file_size = 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;
};
//----------------------------------------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,583 @@
// based on helix aac decoder
#pragma once
//#pragma GCC optimize ("O3")
//#pragma GCC diagnostic ignored "-Wnarrowing"
#include "Arduino.h"
#define AAC_ENABLE_MPEG4
//#define AAC_ENABLE_SBR // needs additional 60KB Heap,
#define ASSERT(x) /* do nothing */
#ifndef MAX
#define MAX(a,b) std::max(a,b)
#endif
#ifndef MIN
#define MIN(a,b) std::min(a,b)
#endif
/* AAC file format */
enum {
AAC_FF_Unknown = 0, /* should be 0 on init */
AAC_FF_ADTS = 1,
AAC_FF_ADIF = 2,
AAC_FF_RAW = 3
};
/* syntactic element type */
enum {
AAC_ID_INVALID = -1,
AAC_ID_SCE = 0,
AAC_ID_CPE = 1,
AAC_ID_CCE = 2,
AAC_ID_LFE = 3,
AAC_ID_DSE = 4,
AAC_ID_PCE = 5,
AAC_ID_FIL = 6,
AAC_ID_END = 7
};
enum {
ERR_AAC_NONE = 0,
ERR_AAC_INDATA_UNDERFLOW = -1,
ERR_AAC_NULL_POINTER = -2,
ERR_AAC_INVALID_ADTS_HEADER = -3,
ERR_AAC_INVALID_ADIF_HEADER = -4,
ERR_AAC_INVALID_FRAME = -5,
ERR_AAC_MPEG4_UNSUPPORTED = -6,
ERR_AAC_CHANNEL_MAP = -7,
ERR_AAC_SYNTAX_ELEMENT = -8,
ERR_AAC_DEQUANT = -9,
ERR_AAC_STEREO_PROCESS = -10,
ERR_AAC_PNS = -11,
ERR_AAC_SHORT_BLOCK_DEINT = -12,
ERR_AAC_TNS = -13,
ERR_AAC_IMDCT = -14,
ERR_AAC_NCHANS_TOO_HIGH = -15,
ERR_AAC_SBR_INIT = -16,
ERR_AAC_SBR_BITSTREAM = -17,
ERR_AAC_SBR_DATA = -18,
ERR_AAC_SBR_PCM_FORMAT = -19,
ERR_AAC_SBR_NCHANS_TOO_HIGH = -20,
ERR_AAC_SBR_SINGLERATE_UNSUPPORTED = -21,
ERR_AAC_RAWBLOCK_PARAMS = -22,
ERR_AAC_UNKNOWN = -9999
};
enum {
SBR_GRID_FIXFIX = 0,
SBR_GRID_FIXVAR = 1,
SBR_GRID_VARFIX = 2,
SBR_GRID_VARVAR = 3
};
enum {
HuffTabSBR_tEnv15 = 0,
HuffTabSBR_fEnv15 = 1,
HuffTabSBR_tEnv15b = 2,
HuffTabSBR_fEnv15b = 3,
HuffTabSBR_tEnv30 = 4,
HuffTabSBR_fEnv30 = 5,
HuffTabSBR_tEnv30b = 6,
HuffTabSBR_fEnv30b = 7,
HuffTabSBR_tNoise30 = 8,
HuffTabSBR_fNoise30 = 5,
HuffTabSBR_tNoise30b = 9,
HuffTabSBR_fNoise30b = 7
};
typedef struct _AACDecInfo_t {
/* raw decoded data, before rounding to 16-bit PCM (for postprocessing such as SBR) */
void *rawSampleBuf[2];
int rawSampleBytes;
int rawSampleFBits;
/* fill data (can be used for processing SBR or other extensions) */
uint8_t *fillBuf;
int fillCount;
int fillExtType;
int prevBlockID; /* block information */
int currBlockID;
int currInstTag;
int sbDeinterleaveReqd[2]; // [MAX_NCHANS_ELEM]
int adtsBlocksLeft;
int bitRate; /* user-accessible info */
int nChans;
int sampRate;
float compressionRatio;
int id; /* 0: MPEG-4, 1: MPEG2 */
int profile; /* 0: Main profile, 1: LowComplexity (LC), 2: ScalableSamplingRate (SSR), 3: reserved */
int format;
int sbrEnabled;
int tnsUsed;
int pnsUsed;
int frameCount;
} AACDecInfo_t;
typedef struct _aac_BitStreamInfo_t {
uint8_t *bytePtr;
unsigned int iCache;
int cachedBits;
int nBytes;
} aac_BitStreamInfo_t;
typedef union _U64 {
int64_t w64;
struct {
unsigned int lo32;
signed int hi32;
} r;
} U64;
typedef struct _AACFrameInfo_t {
int bitRate;
int nChans;
int sampRateCore;
int sampRateOut;
int bitsPerSample;
int outputSamps;
int profile;
int tnsUsed;
int pnsUsed;
} AACFrameInfo_t;
typedef struct _HuffInfo_t {
int maxBits; /* number of bits in longest codeword */
uint8_t count[20]; /* count[MAX_HUFF_BITS] = number of codes with length i+1 bits */
int offset; /* offset into symbol table */
} HuffInfo_t;
typedef struct _PulseInfo_t {
uint8_t pulseDataPresent;
uint8_t numPulse;
uint8_t startSFB;
uint8_t offset[4]; // [MAX_PULSES]
uint8_t amp[4]; // [MAX_PULSES]
} PulseInfo_t;
typedef struct _TNSInfo_t {
uint8_t tnsDataPresent;
uint8_t numFilt[8]; // [MAX_TNS_FILTERS] max 1 filter each for 8 short windows, or 3 filters for 1 long window
uint8_t coefRes[8]; // [MAX_TNS_FILTERS]
uint8_t length[8]; // [MAX_TNS_FILTERS]
uint8_t order[8]; // [MAX_TNS_FILTERS]
uint8_t dir[8]; // [MAX_TNS_FILTERS]
int8_t coef[60]; // [MAX_TNS_COEFS] max 3 filters * 20 coefs for 1 long window,
// or 1 filter * 7 coefs for each of 8 short windows
} TNSInfo_t;
typedef struct _GainControlInfo_t {
uint8_t gainControlDataPresent;
uint8_t maxBand;
uint8_t adjNum[3][8]; // [MAX_GAIN_BANDS][MAX_GAIN_WIN]
uint8_t alevCode[3][8][7]; // [MAX_GAIN_BANDS][MAX_GAIN_WIN][MAX_GAIN_ADJUST]
uint8_t alocCode[3][8][7]; // [MAX_GAIN_BANDS][MAX_GAIN_WIN][MAX_GAIN_ADJUST]
} GainControlInfo_t;
typedef struct _ICSInfo_t {
uint8_t icsResBit;
uint8_t winSequence;
uint8_t winShape;
uint8_t maxSFB;
uint8_t sfGroup;
uint8_t predictorDataPresent;
uint8_t predictorReset;
uint8_t predictorResetGroupNum;
uint8_t predictionUsed[41]; // [MAX_PRED_SFB]
uint8_t numWinGroup;
uint8_t winGroupLen[8]; // [MAX_WIN_GROUPS]
} ICSInfo_t;
typedef struct _ADTSHeader_t {
/* fixed */
uint8_t id; /* MPEG bit - should be 1 */
uint8_t layer; /* MPEG layer - should be 0 */
uint8_t protectBit; /* 0 = CRC word follows, 1 = no CRC word */
uint8_t profile; /* 0 = main, 1 = LC, 2 = SSR, 3 = reserved */
uint8_t sampRateIdx; /* sample rate index range = [0, 11] */
uint8_t privateBit; /* ignore */
uint8_t channelConfig; /* 0 = implicit, >0 = use default table */
uint8_t origCopy; /* 0 = copy, 1 = original */
uint8_t home; /* ignore */
/* variable */
uint8_t copyBit; /* 1 bit of the 72-bit copyright ID (transmitted as 1 bit per frame) */
uint8_t copyStart; /* 1 = this bit starts the 72-bit ID, 0 = it does not */
int frameLength; /* length of frame */
int bufferFull; /* number of 32-bit words left in enc buffer, 0x7FF = VBR */
uint8_t numRawDataBlocks; /* number of raw data blocks in frame */
/* CRC */
int crcCheckWord; /* 16-bit CRC check word (present if protectBit == 0) */
} ADTSHeader_t;
typedef struct _ADIFHeader_t {
uint8_t copyBit; /* 0 = no copyright ID, 1 = 72-bit copyright ID follows immediately */
uint8_t origCopy; /* 0 = copy, 1 = original */
uint8_t home; /* ignore */
uint8_t bsType; /* bitstream type: 0 = CBR, 1 = VBR */
int bitRate; /* bitRate: CBR = bits/sec, VBR = peak bits/frame, 0 = unknown */
uint8_t numPCE; /* number of program config elements (max = 16) */
int bufferFull; /* bits left in bit reservoir */
uint8_t copyID[9]; /* [ADIF_COPYID_SIZE] optional 72-bit copyright ID */
} ADIFHeader_t;
/* sizeof(ProgConfigElement_t) = 82 bytes (if KEEP_PCE_COMMENTS not defined) */
typedef struct _ProgConfigElement_t {
uint8_t elemInstTag; /* element instance tag */
uint8_t profile; /* 0 = main, 1 = LC, 2 = SSR, 3 = reserved */
uint8_t sampRateIdx; /* sample rate index range = [0, 11] */
uint8_t numFCE; /* number of front channel elements (max = 15) */
uint8_t numSCE; /* number of side channel elements (max = 15) */
uint8_t numBCE; /* number of back channel elements (max = 15) */
uint8_t numLCE; /* number of LFE channel elements (max = 3) */
uint8_t numADE; /* number of associated data elements (max = 7) */
uint8_t numCCE; /* number of valid channel coupling elements (max = 15) */
uint8_t monoMixdown; /* mono mixdown: bit 4 = present flag, bits 3-0 = element number */
uint8_t stereoMixdown; /* stereo mixdown: bit 4 = present flag, bits 3-0 = element number */
uint8_t matrixMixdown; /* bit 4 = present flag, bit 3 = unused,bits 2-1 = index, bit 0 = pseudo-surround enable */
uint8_t fce[15]; /* [MAX_NUM_FCE] front element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
uint8_t sce[15]; /* [MAX_NUM_SCE] side element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
uint8_t bce[15]; /* [MAX_NUM_BCE] back element channel pair: bit 4 = SCE/CPE flag, bits 3-0 = inst tag */
uint8_t lce[3]; /* [MAX_NUM_LCE] instance tag for LFE elements */
uint8_t ade[7]; /* [MAX_NUM_ADE] instance tag for ADE elements */
uint8_t cce[15]; /* [MAX_NUM_BCE] channel coupling elements: bit 4 = switching flag, bits 3-0 = inst tag */
} ProgConfigElement_t;
typedef struct _SBRHeader {
int count;
uint8_t ampRes;
uint8_t startFreq;
uint8_t stopFreq;
uint8_t crossOverBand;
uint8_t resBitsHdr;
uint8_t hdrExtra1;
uint8_t hdrExtra2;
uint8_t freqScale;
uint8_t alterScale;
uint8_t noiseBands;
uint8_t limiterBands;
uint8_t limiterGains;
uint8_t interpFreq;
uint8_t smoothMode;
} SBRHeader;
/* need one SBRGrid per channel, updated every frame */
typedef struct _SBRGrid {
uint8_t frameClass;
uint8_t ampResFrame;
uint8_t pointer;
uint8_t numEnv; /* L_E */
uint8_t envTimeBorder[5 + 1]; // [MAX_NUM_ENV+1] /* t_E */
uint8_t freqRes[5]; // [MAX_NUM_ENV]/* r */
uint8_t numNoiseFloors; /* L_Q */
uint8_t noiseTimeBorder[2 + 1]; // [MAX_NUM_NOISE_FLOORS+1] /* t_Q */
uint8_t numEnvPrev;
uint8_t numNoiseFloorsPrev;
uint8_t freqResPrev;
} SBRGrid;
/* need one SBRFreq per element (SCE/CPE/LFE), updated only on header reset */
typedef struct _SBRFreq {
int kStart; /* k_x */
int nMaster;
int nHigh;
int nLow;
int nLimiter; /* N_l */
int numQMFBands; /* M */
int numNoiseFloorBands; /* Nq */
int kStartPrev;
int numQMFBandsPrev;
uint8_t freqMaster[48 + 1]; // [MAX_QMF_BANDS + 1] /* not necessary to save this after derived tables are generated */
uint8_t freqHigh[48 + 1]; // [MAX_QMF_BANDS + 1]
uint8_t freqLow[48 / 2 + 1]; // [MAX_QMF_BANDS / 2 + 1] /* nLow = nHigh - (nHigh >> 1) */
uint8_t freqNoise[5 + 1]; // [MAX_NUM_NOISE_FLOOR_BANDS+1]
uint8_t freqLimiter[48 / 2 + 5];// [MAX_QMF_BANDS / 2 + MAX_NUM_PATCHES] /* max (intermediate) size = nLow + numPatches - 1 */
uint8_t numPatches;
uint8_t patchNumSubbands[5 + 1]; // [MAX_NUM_PATCHES + 1]
uint8_t patchStartSubband[5 + 1]; // [MAX_NUM_PATCHES + 1]
} SBRFreq;
typedef struct _SBRChan {
int reset;
uint8_t deltaFlagEnv[5]; // [MAX_NUM_ENV]
uint8_t deltaFlagNoise[2]; // [MAX_NUM_NOISE_FLOORS]
int8_t envDataQuant[5][48]; // [MAX_NUM_ENV][MAX_QMF_BANDS] /* range = [0, 127] */
int8_t noiseDataQuant[2][5]; // [MAX_NUM_NOISE_FLOORS][MAX_NUM_NOISE_FLOOR_BANDS]
uint8_t invfMode[2][5]; // [2][MAX_NUM_NOISE_FLOOR_BANDS] /* invfMode[0/1][band] = prev/curr */
int chirpFact[5]; // [MAX_NUM_NOISE_FLOOR_BANDS] /* bwArray */
uint8_t addHarmonicFlag[2]; /* addHarmonicFlag[0/1] = prev/curr */
uint8_t addHarmonic[2][64]; /* addHarmonic[0/1][band] = prev/curr */
int gbMask[2]; /* gbMask[0/1] = XBuf[0-31]/XBuf[32-39] */
int8_t laPrev;
int noiseTabIndex;
int sinIndex;
int gainNoiseIndex;
int gTemp[5][48]; // [MAX_NUM_SMOOTH_COEFS][MAX_QMF_BANDS]
int qTemp[5][48]; // [MAX_NUM_SMOOTH_COEFS][MAX_QMF_BANDS]
} SBRChan;
/* state info struct for baseline (MPEG-4 LC) decoding */
typedef struct _PSInfoBase_t {
int dataCount;
uint8_t dataBuf[510]; // [DATA_BUF_SIZE]
int fillCount;
uint8_t fillBuf[269]; //[FILL_BUF_SIZE]
/* state information which is the same throughout whole frame */
int nChans;
int useImpChanMap;
int sampRateIdx;
/* state information which can be overwritten by subsequent elements within frame */
ICSInfo_t icsInfo[2]; // [MAX_NCHANS_ELEM]
int commonWin;
short scaleFactors[2][15*8]; // [MAX_NCHANS_ELEM][MAX_SF_BANDS]
uint8_t sfbCodeBook[2][15*8]; // [MAX_NCHANS_ELEM][MAX_SF_BANDS]
int msMaskPresent;
uint8_t msMaskBits[(15 * 8 + 7) >> 3]; // [MAX_MS_MASK_BYTES]
int pnsUsed[2]; // [MAX_NCHANS_ELEM]
int pnsLastVal;
int intensityUsed[2]; // [MAX_NCHANS_ELEM]
// PulseInfo_t pulseInfo[2]; // [MAX_NCHANS_ELEM]
TNSInfo_t tnsInfo[2]; // [MAX_NCHANS_ELEM]
int tnsLPCBuf[20]; // [MAX_TNS_ORDER]
int tnsWorkBuf[20]; //[MAX_TNS_ORDER]
GainControlInfo_t gainControlInfo[2]; // [MAX_NCHANS_ELEM]
int gbCurrent[2]; // [MAX_NCHANS_ELEM]
int coef[2][1024]; // [MAX_NCHANS_ELEM][AAC_MAX_NSAMPS]
#ifdef AAC_ENABLE_SBR
int sbrWorkBuf[2][1024]; // [MAX_NCHANS_ELEM][AAC_MAX_NSAMPS];
#endif
/* state information which must be saved for each element and used in next frame */
int overlap[2][1024]; // [AAC_MAX_NCHANS][AAC_MAX_NSAMPS]
int prevWinShape[2]; // [AAC_MAX_NCHANS]
} PSInfoBase_t;
typedef struct _PSInfoSBR {
/* save for entire file */
int frameCount;
int sampRateIdx;
/* state info that must be saved for each channel */
SBRHeader sbrHdr[2];
SBRGrid sbrGrid[2];
SBRFreq sbrFreq[2];
SBRChan sbrChan[2];
/* temp variables, no need to save between blocks */
uint8_t dataExtra;
uint8_t resBitsData;
uint8_t extendedDataPresent;
int extendedDataSize;
int8_t envDataDequantScale[2][5]; // [MAX_NCHANS_ELEM][MAX_NUM_ENV
int envDataDequant[2][5][48]; // [MAX_NCHANS_ELEM][MAX_NUM_ENV][MAX_QMF_BANDS
int noiseDataDequant[2][2][5]; // [MAX_NCHANS_ELEM][MAX_NUM_NOISE_FLOORS][MAX_NUM_NOISE_FLOOR_BANDS]
int eCurr[48]; // [MAX_QMF_BANDS]
uint8_t eCurrExp[48]; // [MAX_QMF_BANDS]
uint8_t eCurrExpMax;
int8_t la;
int crcCheckWord;
int couplingFlag;
int envBand;
int eOMGainMax;
int gainMax;
int gainMaxFBits;
int noiseFloorBand;
int qp1Inv;
int qqp1Inv;
int sMapped;
int sBand;
int highBand;
int sumEOrigMapped;
int sumECurrGLim;
int sumSM;
int sumQM;
int gLimBoost[48];
int qmLimBoost[48];
int smBoost[48];
int smBuf[48];
int qmLimBuf[48];
int gLimBuf[48];
int gLimFbits[48];
int gFiltLast[48];
int qFiltLast[48];
/* large buffers */
int delayIdxQMFA[2]; // [AAC_MAX_NCHANS]
int delayQMFA[2][10 * 32]; // [AAC_MAX_NCHANS][DELAY_SAMPS_QMFA]
int delayIdxQMFS[2]; // [AAC_MAX_NCHANS]
int delayQMFS[2][10 * 128]; // [AAC_MAX_NCHANS][DELAY_SAMPS_QMFS]
int XBufDelay[2][8][64][2]; // [AAC_MAX_NCHANS][HF_GEN][64][2]
int XBuf[32+8][64][2];
} PSInfoSBR_t;
bool AACDecoder_AllocateBuffers(void);
int AACFlushCodec();
void AACDecoder_FreeBuffers(void);
bool AACDecoder_IsInit(void);
int AACFindSyncWord(uint8_t *buf, int nBytes);
int AACSetRawBlockParams(int copyLast, int nChans, int sampRateCore, int profile);
int AACDecode(uint8_t *inbuf, int *bytesLeft, short *outbuf);
int AACGetSampRate();
int AACGetChannels();
int AACGetID(); // 0-MPEG4, 1-MPEG2
uint8_t AACGetProfile(); // 0-Main, 1-LC, 2-SSR, 3-reserved
uint8_t AACGetFormat(); // 0-unknown 1-ADTS 2-ADIF, 3-RAW
int AACGetBitsPerSample();
int AACGetBitrate();
int AACGetOutputSamps();
int AACGetBitrate();
void DecodeLPCCoefs(int order, int res, int8_t *filtCoef, int *a, int *b);
int FilterRegion(int size, int dir, int order, int *audioCoef, int *a, int *hist);
int TNSFilter(int ch);
int DecodeSingleChannelElement();
int DecodeChannelPairElement();
int DecodeLFEChannelElement();
int DecodeDataStreamElement();
int DecodeProgramConfigElement(uint8_t idx);
int DecodeFillElement();
int DecodeNextElement(uint8_t **buf, int *bitOffset, int *bitsAvail);
void PreMultiply(int tabidx, int *zbuf1);
void PostMultiply(int tabidx, int *fft1);
void PreMultiplyRescale(int tabidx, int *zbuf1, int es);
void PostMultiplyRescale(int tabidx, int *fft1, int es);
void DCT4(int tabidx, int *coef, int gb);
void BitReverse(int *inout, int tabidx);
void R4FirstPass(int *x, int bg);
void R8FirstPass(int *x, int bg);
void R4Core(int *x, int bg, int gp, int *wtab);
void R4FFT(int tabidx, int *x);
void UnpackZeros(int nVals, int *coef);
void UnpackQuads(int cb, int nVals, int *coef);
void UnpackPairsNoEsc(int cb, int nVals, int *coef);
void UnpackPairsEsc(int cb, int nVals, int *coef);
void DecodeSpectrumLong(int ch);
void DecodeSpectrumShort(int ch);
void DecWindowOverlap(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev);
void DecWindowOverlapLongStart(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev);
void DecWindowOverlapLongStop(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev);
void DecWindowOverlapShort(int *buf0, int *over0, short *pcm0, int nChans, int winTypeCurr, int winTypePrev);
int IMDCT(int ch, int chOut, short *outbuf);
void DecodeICSInfo(ICSInfo_t *icsInfo, int sampRateIdx);
void DecodeSectionData(int winSequence, int numWinGrp, int maxSFB, uint8_t *sfbCodeBook);
int DecodeOneScaleFactor();
void DecodeScaleFactors(int numWinGrp, int maxSFB, int globalGain, uint8_t *sfbCodeBook, short *scaleFactors);
void DecodePulseInfo(uint8_t ch);
void DecodeTNSInfo(int winSequence, TNSInfo_t *ti, int8_t *tnsCoef);
void DecodeGainControlInfo(int winSequence, GainControlInfo_t *gi);
void DecodeICS(int ch);
int DecodeNoiselessData(uint8_t **buf, int *bitOffset, int *bitsAvail, int ch);
int DecodeHuffmanScalar(const signed short *huffTab, const HuffInfo_t *huffTabInfo, unsigned int bitBuf, int32_t *val);
int UnpackADTSHeader(uint8_t **buf, int *bitOffset, int *bitsAvail);
int GetADTSChannelMapping(uint8_t *buf, int bitOffset, int bitsAvail);
int GetNumChannelsADIF(int nPCE);
int GetSampleRateIdxADIF(int nPCE);
int UnpackADIFHeader(uint8_t **buf, int *bitOffset, int *bitsAvail);
int SetRawBlockParams(int copyLast, int nChans, int sampRate, int profile);
int PrepareRawBlock();
int DequantBlock(int *inbuf, int nSamps, int scale);
int AACDequantize(int ch);
int DeinterleaveShortBlocks(int ch);
unsigned int Get32BitVal(unsigned int *last);
int InvRootR(int r);
int ScaleNoiseVector(int *coef, int nVals, int sf);
void GenerateNoiseVector(int *coef, int *last, int nVals);
void CopyNoiseVector(int *coefL, int *coefR, int nVals);
int PNS(int ch);
int GetSampRateIdx(int sampRate);
void StereoProcessGroup(int *coefL, int *coefR, const uint16_t *sfbTab, int msMaskPres, uint8_t *msMaskPtr,
int msMaskOffset, int maxSFB, uint8_t *cbRight, short *sfRight, int *gbCurrent);
int StereoProcess();
int RatioPowInv(int a, int b, int c);
int SqrtFix(int q, int fBitsIn, int *fBitsOut);
int InvRNormalized(int r);
void BitReverse32(int *inout);
void R8FirstPass32(int *r0);
void R4Core32(int *r0);
void FFT32C(int *x);
void CVKernel1(int *XBuf, int *accBuf);
void CVKernel2(int *XBuf, int *accBuf);
void SetBitstreamPointer(int nBytes, uint8_t *buf);
inline void RefillBitstreamCache();
unsigned int GetBits(int nBits);
unsigned int GetBitsNoAdvance(int nBits);
void AdvanceBitstream(int nBits);
int CalcBitsUsed(uint8_t *startBuf, int startOffset);
void ByteAlignBitstream();
// SBR
void InitSBRState();
int DecodeSBRBitstream(int chBase);
int DecodeSBRData(int chBase, short *outbuf);
int FlushCodecSBR();
void BubbleSort(uint8_t *v, int nItems);
uint8_t VMin(uint8_t *v, int nItems);
uint8_t VMax(uint8_t *v, int nItems);
int CalcFreqMasterScaleZero(uint8_t *freqMaster, int alterScale, int k0, int k2);
int CalcFreqMaster(uint8_t *freqMaster, int freqScale, int alterScale, int k0, int k2);
int CalcFreqHigh(uint8_t *freqHigh, uint8_t *freqMaster, int nMaster, int crossOverBand);
int CalcFreqLow(uint8_t *freqLow, uint8_t *freqHigh, int nHigh);
int CalcFreqNoise(uint8_t *freqNoise, uint8_t *freqLow, int nLow, int kStart, int k2, int noiseBands);
int BuildPatches(uint8_t *patchNumSubbands, uint8_t *patchStartSubband, uint8_t *freqMaster, int nMaster, int k0,
int kStart, int numQMFBands, int sampRateIdx);
int FindFreq(uint8_t *freq, int nFreq, uint8_t val);
void RemoveFreq(uint8_t *freq, int nFreq, int removeIdx);
int CalcFreqLimiter(uint8_t *freqLimiter, uint8_t *patchNumSubbands, uint8_t *freqLow, int nLow, int kStart,
int limiterBands, int numPatches);
int CalcFreqTables(SBRHeader *sbrHdr, SBRFreq *sbrFreq, int sampRateIdx);
void EstimateEnvelope(SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, int env);
int GetSMapped(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int env, int band, int la);
void CalcMaxGain(SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, int ch, int env, int lim, int fbitsDQ);
void CalcNoiseDivFactors(int q, int *qp1Inv, int *qqp1Inv);
void CalcComponentGains(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch, int env, int lim, int fbitsDQ);
void ApplyBoost(SBRFreq *sbrFreq, int lim, int fbitsDQ);
void CalcGain(SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch, int env);
void MapHF(SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int env, int hfReset);
void AdjustHighFreq(SBRHeader *sbrHdr, SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
int CalcCovariance1(int *XBuf, int *p01reN, int *p01imN, int *p12reN, int *p12imN, int *p11reN, int *p22reN);
int CalcCovariance2(int *XBuf, int *p02reN, int *p02imN);
void CalcLPCoefs(int *XBuf, int *a0re, int *a0im, int *a1re, int *a1im, int gb);
void GenerateHighFreq(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
int DecodeHuffmanScalar(const signed int *huffTab, const HuffInfo_t *huffTabInfo, unsigned int bitBuf, signed int *val);
int DecodeOneSymbol(int huffTabIndex);
int DequantizeEnvelope(int nBands, int ampRes, int8_t *envQuant, int *envDequant);
void DequantizeNoise(int nBands, int8_t *noiseQuant, int *noiseDequant);
void DecodeSBREnvelope(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
void DecodeSBRNoise(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChan, int ch);
void UncoupleSBREnvelope(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR);
void UncoupleSBRNoise(SBRGrid *sbrGrid, SBRFreq *sbrFreq, SBRChan *sbrChanR);
void DecWindowOverlapNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
void DecWindowOverlapLongStartNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
void DecWindowOverlapLongStopNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
void DecWindowOverlapShortNoClip(int *buf0, int *over0, int *out0, int winTypeCurr, int winTypePrev);
void PreMultiply64(int *zbuf1);
void PostMultiply64(int *fft1, int nSampsOut);
void QMFAnalysisConv(int *cTab, int *delay, int dIdx, int *uBuf);
int QMFAnalysis(int *inbuf, int *delay, int *XBuf, int fBitsIn, int *delayIdx, int qmfaBands);
void QMFSynthesisConv(int *cPtr, int *delay, int dIdx, short *outbuf, int nChans);
void QMFSynthesis(int *inbuf, int *delay, int *delayIdx, int qmfsBands, short *outbuf, int nChans);
int UnpackSBRHeader(SBRHeader *sbrHdr);
void UnpackSBRGrid(SBRHeader *sbrHdr, SBRGrid *sbrGrid);
void UnpackDeltaTimeFreq(int numEnv, uint8_t *deltaFlagEnv, int numNoiseFloors, uint8_t *deltaFlagNoise);
void UnpackInverseFilterMode(int numNoiseFloorBands, uint8_t *mode);
void UnpackSinusoids(int nHigh, int addHarmonicFlag, uint8_t *addHarmonic);
void CopyCouplingGrid(SBRGrid *sbrGridLeft, SBRGrid *sbrGridRight);
void CopyCouplingInverseFilterMode(int numNoiseFloorBands, uint8_t *modeLeft, uint8_t *modeRight);
void UnpackSBRSingleChannel(int chBase);
void UnpackSBRChannelPair(int chBase);

View File

@@ -0,0 +1,556 @@
/*
* flac_decoder.cpp
* Java source code from https://www.nayuki.io/page/simple-flac-implementation
* adapted to ESP32
*
* Created on: Jul 03,2020
* Updated on: Jul 03,2021
*
* Author: Wolle
*
*
*/
#include "flac_decoder.h"
#include "vector"
using namespace std;
FLACFrameHeader_t *FLACFrameHeader;
FLACMetadataBlock_t *FLACMetadataBlock;
FLACsubFramesBuff_t *FLACsubFramesBuff;
vector<int32_t>coefs;
const uint16_t outBuffSize = 2048;
uint16_t m_blockSize=0;
uint16_t m_blockSizeLeft = 0;
uint16_t m_validSamples = 0;
uint8_t m_status = 0;
uint8_t* m_inptr;
int16_t m_bytesAvail;
int16_t m_bytesDecoded = 0;
float m_compressionRatio = 0;
uint16_t m_rIndex=0;
uint64_t m_bitBuffer = 0;
uint8_t m_bitBufferLen = 0;
bool m_f_OggS_found = false;
//----------------------------------------------------------------------------------------------------------------------
// FLAC INI SECTION
//----------------------------------------------------------------------------------------------------------------------
bool FLACDecoder_AllocateBuffers(void){
if(psramFound()) {
// PSRAM found, Buffer will be allocated in PSRAM
if(!FLACFrameHeader) {FLACFrameHeader = (FLACFrameHeader_t*) ps_malloc(sizeof(FLACFrameHeader_t));}
if(!FLACMetadataBlock) {FLACMetadataBlock = (FLACMetadataBlock_t*) ps_malloc(sizeof(FLACMetadataBlock_t));}
if(!FLACsubFramesBuff) {FLACsubFramesBuff = (FLACsubFramesBuff_t*) ps_malloc(sizeof(FLACsubFramesBuff_t));}
}
else {
if(!FLACFrameHeader) {FLACFrameHeader = (FLACFrameHeader_t*) malloc(sizeof(FLACFrameHeader_t));}
if(!FLACMetadataBlock) {FLACMetadataBlock = (FLACMetadataBlock_t*) malloc(sizeof(FLACMetadataBlock_t));}
if(!FLACsubFramesBuff) {FLACsubFramesBuff = (FLACsubFramesBuff_t*) malloc(sizeof(FLACsubFramesBuff_t));}
}
if(!FLACFrameHeader || !FLACMetadataBlock || !FLACsubFramesBuff ){
log_e("not enough memory to allocate flacdecoder buffers");
return false;
}
FLACDecoder_ClearBuffer();
return true;
}
//----------------------------------------------------------------------------------------------------------------------
void FLACDecoder_ClearBuffer(){
memset(FLACFrameHeader, 0, sizeof(FLACFrameHeader_t));
memset(FLACMetadataBlock, 0, sizeof(FLACMetadataBlock_t));
memset(FLACsubFramesBuff, 0, sizeof(FLACsubFramesBuff_t));
m_status = DECODE_FRAME;
return;
}
//----------------------------------------------------------------------------------------------------------------------
void FLACDecoder_FreeBuffers(){
if(FLACFrameHeader) {free(FLACFrameHeader); FLACFrameHeader = NULL;}
if(FLACMetadataBlock) {free(FLACMetadataBlock); FLACMetadataBlock = NULL;}
if(FLACsubFramesBuff) {free(FLACsubFramesBuff); FLACsubFramesBuff = NULL;}
}
//----------------------------------------------------------------------------------------------------------------------
// B I T R E A D E R
//----------------------------------------------------------------------------------------------------------------------
uint32_t readUint(uint8_t nBits){
while (m_bitBufferLen < nBits){
uint8_t temp = *(m_inptr + m_rIndex);
m_rIndex++;
m_bytesAvail--;
if(m_bytesAvail < 0) { log_i("error in bitreader"); }
m_bitBuffer = (m_bitBuffer << 8) | temp;
m_bitBufferLen += 8;
}
m_bitBufferLen -= nBits;
uint32_t result = m_bitBuffer >> m_bitBufferLen;
if (nBits < 32)
result &= (1 << nBits) - 1;
return result;
}
int32_t readSignedInt(int nBits){
int32_t temp = readUint(nBits) << (32 - nBits);
temp = temp >> (32 - nBits); // The C++ compiler uses the sign bit to fill vacated bit positions
return temp;
}
int64_t readRiceSignedInt(uint8_t param){
long val = 0;
while (readUint(1) == 0)
val++;
val = (val << param) | readUint(param);
return (val >> 1) ^ -(val & 1);
}
void alignToByte() {
m_bitBufferLen -= m_bitBufferLen % 8;
}
//----------------------------------------------------------------------------------------------------------------------
// F L A C - D E C O D E R
//----------------------------------------------------------------------------------------------------------------------
void FLACSetRawBlockParams(uint8_t Chans, uint32_t SampRate, uint8_t BPS, uint32_t tsis, uint32_t AuDaLength){
FLACMetadataBlock->numChannels = Chans;
FLACMetadataBlock->sampleRate = SampRate;
FLACMetadataBlock->bitsPerSample = BPS;
FLACMetadataBlock->totalSamples = tsis; // total samples in stream
FLACMetadataBlock->audioDataLength = AuDaLength;
}
//----------------------------------------------------------------------------------------------------------------------
void FLACDecoderReset(){ // set var to default
m_status = DECODE_FRAME;
m_bitBuffer = 0;
m_bitBufferLen = 0;
}
//----------------------------------------------------------------------------------------------------------------------
int FLACFindSyncWord(unsigned char *buf, int nBytes) {
int i;
/* find byte-aligned syncword - need 13 matching bits */
for (i = 0; i < nBytes - 1; i++) {
if ((buf[i + 0] & 0xFF) == 0xFF && (buf[i + 1] & 0xF8) == 0xF8) {
FLACDecoderReset();
return i;
}
}
return -1;
}
//----------------------------------------------------------------------------------------------------------------------
int FLACFindOggSyncWord(unsigned char *buf, int nBytes){
int i;
/* find byte-aligned syncword - need 13 matching bits */
for (i = 0; i < nBytes - 1; i++) {
if ((buf[i + 0] & 0xFF) == 0xFF && (buf[i + 1] & 0xF8) == 0xF8) {
FLACDecoderReset();
log_i("FLAC sync found");
return i;
}
}
/* find byte-aligned OGG Magic - OggS */
for (i = 0; i < nBytes - 1; i++) {
if ((buf[i + 0] == 'O') && (buf[i + 1] == 'g') && (buf[i + 2] == 'g') && (buf[i + 3] == 'S')) {
FLACDecoderReset();
log_i("OggS found");
m_f_OggS_found = true;
return i;
}
}
return -1;
}
//----------------------------------------------------------------------------------------------------------------------
int FLACparseOggHeader(unsigned char *buf){
uint8_t i = 0;
uint8_t ssv = *(buf + i); // stream_structure_version
(void)ssv;
i++;
uint8_t htf = *(buf + i); // header_type_flag
(void)htf;
i++;
uint32_t tmp = 0; // absolute granule position
for (int j = 0; j < 4; j++) {
tmp += *(buf + j + i) << (4 -j - 1) * 8;
}
i += 4;
uint64_t agp = (uint64_t) tmp << 32;
for (int j = 0; j < 4; j++) {
agp += *(buf + j + i) << (4 -j - 1) * 8;
}
i += 4;
uint32_t ssnr = 0; // stream serial number
for (int j = 0; j < 4; j++) {
ssnr += *(buf + j + i) << (4 -j - 1) * 8;
}
i += 4;
uint32_t psnr = 0; // page sequence no
for (int j = 0; j < 4; j++) {
psnr += *(buf + j + i) << (4 -j - 1) * 8;
}
i += 4;
uint32_t pchk = 0; // page checksum
for (int j = 0; j < 4; j++) {
pchk += *(buf + j + i) << (4 -j - 1) * 8;
}
i += 4;
uint8_t psegm = *(buf + i);
i++;
uint8_t psegmBuff[256];
uint32_t pageLen = 0;
for(uint8_t j = 0; j < psegm; j++){
psegmBuff[j] = *(buf + i);
pageLen += psegmBuff[j];
i++;
}
return i;
}
//----------------------------------------------------------------------------------------------------------------------
int8_t FLACDecode(uint8_t *inbuf, int *bytesLeft, short *outbuf){
if(m_f_OggS_found == true){
m_f_OggS_found = false;
*bytesLeft -= FLACparseOggHeader(inbuf);
return ERR_FLAC_NONE;
}
if(m_status != OUT_SAMPLES){
m_rIndex = 0;
m_bytesAvail = (*bytesLeft);
m_inptr = inbuf;
}
if(m_status == DECODE_FRAME){ // Read a ton of header fields, and ignore most of them
if ((inbuf[0] == 'O') && (inbuf[1] == 'g') && (inbuf[2] == 'g') && (inbuf[3] == 'S')){
*bytesLeft -= 4;
m_f_OggS_found = true;
return ERR_FLAC_NONE;
}
uint32_t temp = readUint(8);
uint16_t sync = temp << 6 |readUint(6);
if (sync != 0x3FFE){
log_i("Sync code expected 0x3FFE but received %X", sync);
return ERR_FLAC_SYNC_CODE_NOT_FOUND;
}
readUint(1);
FLACFrameHeader->blockingStrategy = readUint(1);
FLACFrameHeader->blockSizeCode = readUint(4);
FLACFrameHeader->sampleRateCode = readUint(4);
FLACFrameHeader->chanAsgn = readUint(4);
FLACFrameHeader->sampleSizeCode = readUint(3);
if(!FLACMetadataBlock->numChannels){
if(FLACFrameHeader->chanAsgn == 0) FLACMetadataBlock->numChannels = 1;
if(FLACFrameHeader->chanAsgn == 1) FLACMetadataBlock->numChannels = 2;
if(FLACFrameHeader->chanAsgn > 7) FLACMetadataBlock->numChannels = 2;
}
if(FLACMetadataBlock->numChannels < 1) return ERR_FLAC_UNKNOWN_CHANNEL_ASSIGNMENT;
if(!FLACMetadataBlock->bitsPerSample){
if(FLACFrameHeader->sampleSizeCode == 1) FLACMetadataBlock->bitsPerSample = 8;
if(FLACFrameHeader->sampleSizeCode == 2) FLACMetadataBlock->bitsPerSample = 12;
if(FLACFrameHeader->sampleSizeCode == 4) FLACMetadataBlock->bitsPerSample = 16;
if(FLACFrameHeader->sampleSizeCode == 5) FLACMetadataBlock->bitsPerSample = 20;
if(FLACFrameHeader->sampleSizeCode == 6) FLACMetadataBlock->bitsPerSample = 24;
}
if(FLACMetadataBlock->bitsPerSample > 16) return ERR_FLAC_BITS_PER_SAMPLE_TOO_BIG;
if(FLACMetadataBlock->bitsPerSample < 8 ) return ERR_FLAG_BITS_PER_SAMPLE_UNKNOWN;
if(!FLACMetadataBlock->sampleRate){
if(FLACFrameHeader->sampleRateCode == 1) FLACMetadataBlock->sampleRate = 88200;
if(FLACFrameHeader->sampleRateCode == 2) FLACMetadataBlock->sampleRate = 176400;
if(FLACFrameHeader->sampleRateCode == 3) FLACMetadataBlock->sampleRate = 192000;
if(FLACFrameHeader->sampleRateCode == 4) FLACMetadataBlock->sampleRate = 8000;
if(FLACFrameHeader->sampleRateCode == 5) FLACMetadataBlock->sampleRate = 16000;
if(FLACFrameHeader->sampleRateCode == 6) FLACMetadataBlock->sampleRate = 22050;
if(FLACFrameHeader->sampleRateCode == 7) FLACMetadataBlock->sampleRate = 24000;
if(FLACFrameHeader->sampleRateCode == 8) FLACMetadataBlock->sampleRate = 32000;
if(FLACFrameHeader->sampleRateCode == 9) FLACMetadataBlock->sampleRate = 44100;
if(FLACFrameHeader->sampleRateCode == 10) FLACMetadataBlock->sampleRate = 48000;
if(FLACFrameHeader->sampleRateCode == 11) FLACMetadataBlock->sampleRate = 96000;
}
readUint(1);
temp = (readUint(8) << 24);
temp = ~temp;
uint32_t shift = 0x80000000; // Number of leading zeros
int8_t count = 0;
for(int i=0; i<32; i++){
if((temp & shift) == 0) {count++; shift >>= 1;}
else break;
}
count--;
for (int i = 0; i < count; i++) readUint(8);
m_blockSize = 0;
if (FLACFrameHeader->blockSizeCode == 1)
m_blockSize = 192;
else if (2 <= FLACFrameHeader->blockSizeCode && FLACFrameHeader->blockSizeCode <= 5)
m_blockSize = 576 << (FLACFrameHeader->blockSizeCode - 2);
else if (FLACFrameHeader->blockSizeCode == 6)
m_blockSize = readUint(8) + 1;
else if (FLACFrameHeader->blockSizeCode == 7)
m_blockSize = readUint(16) + 1;
else if (8 <= FLACFrameHeader->blockSizeCode && FLACFrameHeader->blockSizeCode <= 15)
m_blockSize = 256 << (FLACFrameHeader->blockSizeCode - 8);
else{
return ERR_FLAC_RESERVED_BLOCKSIZE_UNSUPPORTED;
}
if(m_blockSize > 8192){
log_e("Error: blockSize too big");
return ERR_FLAC_BLOCKSIZE_TOO_BIG;
}
if(FLACFrameHeader->sampleRateCode == 12)
readUint(8);
else if (FLACFrameHeader->sampleRateCode == 13 || FLACFrameHeader->sampleRateCode == 14){
readUint(16);
}
readUint(8);
m_status = DECODE_SUBFRAMES;
*bytesLeft = m_bytesAvail;
m_blockSizeLeft = m_blockSize;
return ERR_FLAC_NONE;
}
if(m_status == DECODE_SUBFRAMES){
// Decode each channel's subframe, then skip footer
int ret = decodeSubframes();
if(ret != 0) return ret;
m_status = OUT_SAMPLES;
}
if(m_status == OUT_SAMPLES){ // Write the decoded samples
// blocksize can be much greater than outbuff, so we can't stuff all in once
// therefore we need often more than one loop (split outputblock into pieces)
uint16_t blockSize;
static uint16_t offset = 0;
if(m_blockSize < outBuffSize + offset) blockSize = m_blockSize - offset;
else blockSize = outBuffSize;
for (int i = 0; i < blockSize; i++) {
for (int j = 0; j < FLACMetadataBlock->numChannels; j++) {
int val = FLACsubFramesBuff->samplesBuffer[j][i + offset];
if (FLACMetadataBlock->bitsPerSample == 8) val += 128;
outbuf[2*i+j] = val;
}
}
m_validSamples = blockSize * FLACMetadataBlock->numChannels;
offset += blockSize;
if(offset != m_blockSize) return GIVE_NEXT_LOOP;
offset = 0;
if(offset > m_blockSize) { log_e("offset has a wrong value"); }
}
alignToByte();
readUint(16);
m_bytesDecoded = *bytesLeft - m_bytesAvail;
// log_i("m_bytesDecoded %i", m_bytesDecoded);
// m_compressionRatio = (float)m_bytesDecoded / (float)m_blockSize * FLACMetadataBlock->numChannels * (16/8);
// log_i("m_compressionRatio % f", m_compressionRatio);
*bytesLeft = m_bytesAvail;
m_status = DECODE_FRAME;
return ERR_FLAC_NONE;
}
//----------------------------------------------------------------------------------------------------------------------
uint16_t FLACGetOutputSamps(){
int vs = m_validSamples;
m_validSamples=0;
return vs;
}
//----------------------------------------------------------------------------------------------------------------------
uint64_t FLACGetTotoalSamplesInStream(){
return FLACMetadataBlock->totalSamples;
}
//----------------------------------------------------------------------------------------------------------------------
uint8_t FLACGetBitsPerSample(){
return FLACMetadataBlock->bitsPerSample;
}
//----------------------------------------------------------------------------------------------------------------------
uint8_t FLACGetChannels(){
return FLACMetadataBlock->numChannels;
}
//----------------------------------------------------------------------------------------------------------------------
uint32_t FLACGetSampRate(){
return FLACMetadataBlock->sampleRate;
}
//----------------------------------------------------------------------------------------------------------------------
uint32_t FLACGetBitRate(){
if(FLACMetadataBlock->totalSamples){
float BitsPerSamp = (float)FLACMetadataBlock->audioDataLength / (float)FLACMetadataBlock->totalSamples * 8;
return ((uint32_t)BitsPerSamp * FLACMetadataBlock->sampleRate);
}
return 0;
}
//----------------------------------------------------------------------------------------------------------------------
uint32_t FLACGetAudioFileDuration() {
if(FLACGetSampRate()){
uint32_t afd = FLACGetTotoalSamplesInStream()/ FLACGetSampRate(); // AudioFileDuration
return afd;
}
return 0;
}
//----------------------------------------------------------------------------------------------------------------------
int8_t decodeSubframes(){
if(FLACFrameHeader->chanAsgn <= 7) {
for (int ch = 0; ch < FLACMetadataBlock->numChannels; ch++)
decodeSubframe(FLACMetadataBlock->bitsPerSample, ch);
}
else if (8 <= FLACFrameHeader->chanAsgn && FLACFrameHeader->chanAsgn <= 10) {
decodeSubframe(FLACMetadataBlock->bitsPerSample + (FLACFrameHeader->chanAsgn == 9 ? 1 : 0), 0);
decodeSubframe(FLACMetadataBlock->bitsPerSample + (FLACFrameHeader->chanAsgn == 9 ? 0 : 1), 1);
if(FLACFrameHeader->chanAsgn == 8) {
for (int i = 0; i < m_blockSize; i++)
FLACsubFramesBuff->samplesBuffer[1][i] = (
FLACsubFramesBuff->samplesBuffer[0][i] -
FLACsubFramesBuff->samplesBuffer[1][i]);
}
else if (FLACFrameHeader->chanAsgn == 9) {
for (int i = 0; i < m_blockSize; i++)
FLACsubFramesBuff->samplesBuffer[0][i] += FLACsubFramesBuff->samplesBuffer[1][i];
}
else if (FLACFrameHeader->chanAsgn == 10) {
for (int i = 0; i < m_blockSize; i++) {
long side = FLACsubFramesBuff->samplesBuffer[1][i];
long right = FLACsubFramesBuff->samplesBuffer[0][i] - (side >> 1);
FLACsubFramesBuff->samplesBuffer[1][i] = right;
FLACsubFramesBuff->samplesBuffer[0][i] = right + side;
}
}
else {
log_e("unknown channel assignment");
return ERR_FLAC_UNKNOWN_CHANNEL_ASSIGNMENT;
}
}
else{
log_e("Reserved channel assignment");
return ERR_FLAC_RESERVED_CHANNEL_ASSIGNMENT;
}
return ERR_FLAC_NONE;
}
//----------------------------------------------------------------------------------------------------------------------
int8_t decodeSubframe(uint8_t sampleDepth, uint8_t ch) {
int8_t ret = 0;
readUint(1);
uint8_t type = readUint(6);
int shift = readUint(1);
if (shift == 1) {
while (readUint(1) == 0)
shift++;
}
sampleDepth -= shift;
if(type == 0){ // Constant coding
int16_t s= readSignedInt(sampleDepth);
for(int i=0; i < m_blockSize; i++){
FLACsubFramesBuff->samplesBuffer[ch][i] = s;
}
}
else if (type == 1) { // Verbatim coding
for (int i = 0; i < m_blockSize; i++)
FLACsubFramesBuff->samplesBuffer[ch][i] = readSignedInt(sampleDepth);
}
else if (8 <= type && type <= 12){
ret = decodeFixedPredictionSubframe(type - 8, sampleDepth, ch);
if(ret) return ret;
}
else if (32 <= type && type <= 63){
ret = decodeLinearPredictiveCodingSubframe(type - 31, sampleDepth, ch);
if(ret) return ret;
}
else{
return ERR_FLAC_RESERVED_SUB_TYPE;
}
if(shift>0){
for (int i = 0; i < m_blockSize; i++){
FLACsubFramesBuff->samplesBuffer[ch][i] <<= shift;
}
}
return ERR_FLAC_NONE;
}
//----------------------------------------------------------------------------------------------------------------------
int8_t decodeFixedPredictionSubframe(uint8_t predOrder, uint8_t sampleDepth, uint8_t ch) {
uint8_t ret = 0;
for(uint8_t i = 0; i < predOrder; i++)
FLACsubFramesBuff->samplesBuffer[ch][i] = readSignedInt(sampleDepth);
ret = decodeResiduals(predOrder, ch);
if(ret) return ret;
coefs.clear();
if(predOrder == 0) coefs.resize(0);
if(predOrder == 1) coefs.push_back(1); // FIXED_PREDICTION_COEFFICIENTS
if(predOrder == 2){coefs.push_back(2); coefs.push_back(-1);}
if(predOrder == 3){coefs.push_back(3); coefs.push_back(-3); coefs.push_back(1);}
if(predOrder == 4){coefs.push_back(4); coefs.push_back(-6); coefs.push_back(4); coefs.push_back(-1);}
if(predOrder > 4) return ERR_FLAC_PREORDER_TOO_BIG; // Error: preorder > 4"
restoreLinearPrediction(ch, 0);
return ERR_FLAC_NONE;
}
//----------------------------------------------------------------------------------------------------------------------
int8_t decodeLinearPredictiveCodingSubframe(int lpcOrder, int sampleDepth, uint8_t ch){
int8_t ret = 0;
for (int i = 0; i < lpcOrder; i++)
FLACsubFramesBuff->samplesBuffer[ch][i] = readSignedInt(sampleDepth);
int precision = readUint(4) + 1;
int shift = readSignedInt(5);
coefs.resize(0);
for (uint8_t i = 0; i < lpcOrder; i++)
coefs.push_back(readSignedInt(precision));
ret = decodeResiduals(lpcOrder, ch);
if(ret) return ret;
restoreLinearPrediction(ch, shift);
return ERR_FLAC_NONE;
}
//----------------------------------------------------------------------------------------------------------------------
int8_t decodeResiduals(uint8_t warmup, uint8_t ch) {
int method = readUint(2);
if (method >= 2)
return ERR_FLAC_RESERVED_RESIDUAL_CODING; // Reserved residual coding method
uint8_t paramBits = method == 0 ? 4 : 5;
int escapeParam = (method == 0 ? 0xF : 0x1F);
int partitionOrder = readUint(4);
int numPartitions = 1 << partitionOrder;
if (m_blockSize % numPartitions != 0)
return ERR_FLAC_WRONG_RICE_PARTITION_NR; //Error: Block size not divisible by number of Rice partitions
int partitionSize = m_blockSize/ numPartitions;
for (int i = 0; i < numPartitions; i++) {
int start = i * partitionSize + (i == 0 ? warmup : 0);
int end = (i + 1) * partitionSize;
int param = readUint(paramBits);
if (param < escapeParam) {
for (int j = start; j < end; j++){
FLACsubFramesBuff->samplesBuffer[ch][j] = readRiceSignedInt(param);
}
} else {
int numBits = readUint(5);
for (int j = start; j < end; j++){
FLACsubFramesBuff->samplesBuffer[ch][j] = readSignedInt(numBits);
}
}
}
return ERR_FLAC_NONE;
}
//----------------------------------------------------------------------------------------------------------------------
void restoreLinearPrediction(uint8_t ch, uint8_t shift) {
for (int i = coefs.size(); i < m_blockSize; i++) {
int32_t sum = 0;
for (int j = 0; j < coefs.size(); j++){
sum += FLACsubFramesBuff->samplesBuffer[ch][i - 1 - j] * coefs[j];
}
FLACsubFramesBuff->samplesBuffer[ch][i] += (sum >> shift);
}
}
//----------------------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,175 @@
/*
* flac_decoder.h
*
* Created on: Jul 03,2020
* Updated on: Apr 27,2021
*
* Author: wolle
*
* Restrictions:
* blocksize must not exceed 8192
* bits per sample must be 8 or 16
* num Channels must be 1 or 2
*
*
*/
#pragma once
#pragma GCC optimize ("Ofast")
#include "Arduino.h"
#define MAX_CHANNELS 2
#define MAX_BLOCKSIZE 8192
#define APLL_DISABLE 0
#define EXTERNAL_I2S 0
typedef struct FLACsubFramesBuff_t{
int32_t samplesBuffer[MAX_CHANNELS][MAX_BLOCKSIZE];
}FLACsubframesBuffer_t;
enum : uint8_t {FLACDECODER_INIT, FLACDECODER_READ_IN, FLACDECODER_WRITE_OUT};
enum : uint8_t {DECODE_FRAME, DECODE_SUBFRAMES, OUT_SAMPLES};
enum : int8_t {GIVE_NEXT_LOOP = +1,
ERR_FLAC_NONE = 0,
ERR_FLAC_BLOCKSIZE_TOO_BIG = -1,
ERR_FLAC_RESERVED_BLOCKSIZE_UNSUPPORTED = -2,
ERR_FLAC_SYNC_CODE_NOT_FOUND = -3,
ERR_FLAC_UNKNOWN_CHANNEL_ASSIGNMENT = -4,
ERR_FLAC_RESERVED_CHANNEL_ASSIGNMENT = -5,
ERR_FLAC_RESERVED_SUB_TYPE = -6,
ERR_FLAC_PREORDER_TOO_BIG = -7,
ERR_FLAC_RESERVED_RESIDUAL_CODING = -8,
ERR_FLAC_WRONG_RICE_PARTITION_NR = -9,
ERR_FLAC_BITS_PER_SAMPLE_TOO_BIG = -10,
ERR_FLAG_BITS_PER_SAMPLE_UNKNOWN = 11};
typedef struct FLACMetadataBlock_t{
// METADATA_BLOCK_STREAMINFO
uint16_t minblocksize; // The minimum block size (in samples) used in the stream.
//----------------------------------------------------------------------------------------
// The maximum block size (in samples) used in the stream.
uint16_t maxblocksize; // (Minimum blocksize == maximum blocksize) implies a fixed-blocksize stream.
//----------------------------------------------------------------------------------------
// The minimum frame size (in bytes) used in the stream.
uint32_t minframesize; // May be 0 to imply the value is not known.
//----------------------------------------------------------------------------------------
// The maximum frame size (in bytes) used in the stream.
uint32_t maxframesize; // May be 0 to imply the value is not known.
//----------------------------------------------------------------------------------------
// Sample rate in Hz. Though 20 bits are available,
// the maximum sample rate is limited by the structure of frame headers to 655350Hz.
uint32_t sampleRate; // Also, a value of 0 is invalid.
//----------------------------------------------------------------------------------------
// Number of channels FLAC supports from 1 to 8 channels
uint8_t numChannels; // 000 : 1 channel .... 111 : 8 channels
//----------------------------------------------------------------------------------------
// Sample size in bits:
// 000 : get from STREAMINFO metadata block
// 001 : 8 bits per sample
// 010 : 12 bits per sample
// 011 : reserved
// 100 : 16 bits per sample
// 101 : 20 bits per sample
// 110 : 24 bits per sample
uint8_t bitsPerSample; // 111 : reserved
//----------------------------------------------------------------------------------------
// Total samples in stream. 'Samples' means inter-channel sample,
// i.e. one second of 44.1Khz audio will have 44100 samples regardless of the number
uint64_t totalSamples; // of channels. A value of zero here means the number of total samples is unknown.
//----------------------------------------------------------------------------------------
uint32_t audioDataLength;// is not the filelength, is only the length of the audio datablock in bytes
}FLACMetadataBlock_t;
typedef struct FLACFrameHeader_t {
// 0 : fixed-blocksize stream; frame header encodes the frame number
uint8_t blockingStrategy; // 1 : variable-blocksize stream; frame header encodes the sample number
//----------------------------------------------------------------------------------------
// Block size in inter-channel samples:
// 0000 : reserved
// 0001 : 192 samples
// 0010-0101 : 576 * (2^(n-2)) samples, i.e. 576/1152/2304/4608
// 0110 : get 8 bit (blocksize-1) from end of header
// 0111 : get 16 bit (blocksize-1) from end of header
uint8_t blockSizeCode; // 1000-1111 : 256 * (2^(n-8)) samples, i.e. 256/512/1024/2048/4096/8192/16384/32768
//----------------------------------------------------------------------------------------
// 0000 : get from STREAMINFO metadata block
// 0001 : 88.2kHz
// 0010 : 176.4kHz
// 0011 : 192kHz
// 0100 : 8kHz
// 0101 : 16kHz
// 0110 : 22.05kHz
// 0111 : 24kHz
// 1000 : 32kHz
// 1001 : 44.1kHz
// 1010 : 48kHz
// 1011 : 96kHz
// 1100 : get 8 bit sample rate (in kHz) from end of header
// 1101 : get 16 bit sample rate (in Hz) from end of header
// 1110 : get 16 bit sample rate (in tens of Hz) from end of header
uint8_t sampleRateCode; // 1111 : invalid, to prevent sync-fooling string of 1s
//----------------------------------------------------------------------------------------
// Channel assignment
// 0000 1 channel: mono
// 0001 2 channels: left, right
// 0010 3 channels
// 0011 4 channels
// 0100 5 channels
// 0101 6 channels
// 0110 7 channels
// 0111 8 channels
// 1000 : left/side stereo: channel 0 is the left channel, channel 1 is the side(difference) channel
// 1001 : right/side stereo: channel 0 is the side(difference) channel, channel 1 is the right channel
// 1010 : mid/side stereo: channel 0 is the mid(average) channel, channel 1 is the side(difference) channel
uint8_t chanAsgn; // 1011-1111 : reserved
//----------------------------------------------------------------------------------------
// Sample size in bits:
// 000 : get from STREAMINFO metadata block
// 001 : 8 bits per sample
// 010 : 12 bits per sample
// 011 : reserved
// 100 : 16 bits per sample
// 101 : 20 bits per sample
// 110 : 24 bits per sample
uint8_t sampleSizeCode; // 111 : reserved
//----------------------------------------------------------------------------------------
uint32_t totalSamples; // totalSamplesInStream
//----------------------------------------------------------------------------------------
uint32_t bitrate; // bitrate
}FLACFrameHeader_t;
int FLACFindSyncWord(unsigned char *buf, int nBytes);
int FLACFindOggSyncWord(unsigned char *buf, int nBytes);
int FLACparseOggHeader(unsigned char *buf);
bool FLACDecoder_AllocateBuffers(void);
void FLACDecoder_ClearBuffer();
void FLACDecoder_FreeBuffers();
void FLACSetRawBlockParams(uint8_t Chans, uint32_t SampRate, uint8_t BPS, uint32_t tsis, uint32_t AuDaLength);
void FLACDecoderReset();
int8_t FLACDecode(uint8_t *inbuf, int *bytesLeft, short *outbuf);
uint16_t FLACGetOutputSamps();
uint64_t FLACGetTotoalSamplesInStream();
uint8_t FLACGetBitsPerSample();
uint8_t FLACGetChannels();
uint32_t FLACGetSampRate();
uint32_t FLACGetBitRate();
uint32_t FLACGetAudioFileDuration();
uint32_t readUint(uint8_t nBits);
int32_t readSignedInt(int nBits);
int64_t readRiceSignedInt(uint8_t param);
void alignToByte();
int8_t decodeSubframes();
int8_t decodeSubframe(uint8_t sampleDepth, uint8_t ch);
int8_t decodeFixedPredictionSubframe(uint8_t predOrder, uint8_t sampleDepth, uint8_t ch);
int8_t decodeLinearPredictiveCodingSubframe(int lpcOrder, int sampleDepth, uint8_t ch);
int8_t decodeResiduals(uint8_t warmup, uint8_t ch);
void restoreLinearPrediction(uint8_t ch, uint8_t shift);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,513 @@
// 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 {
int bitrate;
int nChans;
int samprate;
int bitsPerSample;
int outputSamps;
int layer;
int version;
} MP3FrameInfo_t;
typedef struct SFBandTable {
int/*short*/ l[23];
int/*short*/ s[14];
} SFBandTable_t;
typedef struct BitStreamInfo {
unsigned char *bytePtr;
unsigned int iCache;
int cachedBits;
int 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 {
int layer; /* layer index (1, 2, or 3) */
int crc; /* CRC flag: 0 = disabled, 1 = enabled */
int brIdx; /* bitrate index (0 - 15) */
int srIdx; /* sample rate index (0 - 2) */
int paddingBit; /* padding flag: 0 = no padding, 1 = single pad byte */
int privateBit; /* unused */
int modeExt; /* used to decipher joint stereo mode */
int copyFlag; /* copyright flag: 0 = no, 1 = yes */
int origFlag; /* original flag: 0 = copy, 1 = original */
int emphasis; /* deemphasis mode */
int CRCWord; /* CRC word (16 bits, 0 if crc not enabled) */
} FrameHeader_t;
typedef struct SideInfoSub {
int part23Length; /* number of bits in main data */
int nBigvals; /* 2x this = first set of Huffman cw's (maximum amplitude can be > 1) */
int globalGain; /* overall gain for dequantizer */
int sfCompress; /* unpacked to figure out number of bits in scale factors */
int winSwitchFlag; /* window switching flag */
int blockType; /* block type */
int mixedBlock; /* 0 = regular block (all short or long), 1 = mixed block */
int tableSelect[3]; /* index of Huffman tables for the big values regions */
int subBlockGain[3]; /* subblock gain offset, relative to global gain */
int region0Count; /* 1+region0Count = num scale factor bands in first region of bigvals */
int region1Count; /* 1+region1Count = num scale factor bands in second region of bigvals */
int preFlag; /* for optional high frequency boost */
int sfactScale; /* scaling of the scalefactors */
int count1TableSelect; /* index of Huffman table for quad codewords */
} SideInfoSub_t;
typedef struct SideInfo {
int mainDataBegin;
int privateBits;
int scfsi[m_MAX_NCHAN][m_MAX_SCFBD]; /* 4 scalefactor bands per channel */
} SideInfo_t;
typedef struct {
int cbType; /* pure long = 0, pure short = 1, mixed = 2 */
int cbEndS[3]; /* number nonzero short cb's, per subbblock */
int cbEndSMax; /* max of cbEndS[] */
int cbEndL; /* number nonzero long cb's */
} CriticalBandInfo_t;
typedef struct DequantInfo {
int workBuf[m_MAX_REORDER_SAMPS]; /* workbuf for reordering short blocks */
} DequantInfo_t;
typedef struct HuffmanInfo {
int huffDecBuf[m_MAX_NCHAN][m_MAX_NSAMP]; /* used both for decoded Huffman values and dequantized coefficients */
int nonZeroBound[m_MAX_NCHAN]; /* number of coeffs in huffDecBuf[ch] which can be > 0 */
int 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 {
int linBits;
int tabType; /*HuffTabType*/
} HuffTabLookup_t;
typedef struct IMDCTInfo {
int outBuf[m_MAX_NCHAN][m_BLOCK_SIZE][m_NBANDS]; /* output of IMDCT */
int overBuf[m_MAX_NCHAN][m_MAX_NSAMP / 2]; /* overlap-add buffer (by symmetry, only need 1/2 size) */
int numPrevIMDCT[m_MAX_NCHAN]; /* how many IMDCT's calculated in this channel on prev. granule */
int prevType[m_MAX_NCHAN];
int prevWinSwitch[m_MAX_NCHAN];
int gb[m_MAX_NCHAN];
} IMDCTInfo_t;
typedef struct BlockCount {
int nBlocksLong;
int nBlocksTotal;
int nBlocksPrev;
int prevType;
int prevWinSwitch;
int currWinSwitch;
int gbIn;
int 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 */
int intensityScale;
int slen[4];
int 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 {
int vbuf[m_MAX_NCHAN * m_VBUF_LENGTH]; /* vbuf for fast DCT-based synthesis PQMF - double size for speed (no modulo indexing) */
int 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 */
unsigned char mainBuf[m_MAINBUF_SIZE];
/* special info for "free" bitrate files */
int freeBitrateFlag;
int freeBitrateSlots;
/* user-accessible info */
int bitrate;
int nChans;
int samprate;
int nGrans; /* granules per frame */
int nGranSamps; /* samples per granule */
int nSlots;
int layer;
int mainDataBegin;
int mainDataBytes;
int 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 int c9_0 = 0x6ed9eba1;
const int c9_1 = 0x620dbe8b;
const int c9_2 = 0x163a1a7e;
const int c9_3 = 0x5246dd49;
const int c9_4 = 0x7e0e2e32;
const int c3_0 = 0x6ed9eba1; /* format = Q31, cos(pi/6) */
const int 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 int 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 unsigned int poly43lo[5] PROGMEM = { 0x29a0bda9, 0xb02e4828, 0x5957aa1b, 0x236c498d, 0xff581859 };
const unsigned int poly43hi[5] PROGMEM = { 0x10852163, 0xd333f6a4, 0x46e9408b, 0x27c2cef0, 0xfef577b4 };
/* pow(2, i*4/3) as exp and frac */
const int pow2exp[8] PROGMEM = { 14, 13, 11, 10, 9, 7, 6, 5 };
const int 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 int 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 int quadTabOffset[2] PROGMEM = {0, 64};
const int quadTabMaxBits[2] PROGMEM = {6, 4};
/* indexing = [version][samplerate index]
* sample rate of frame (Hz)
*/
const int 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 int/*short*/samplesPerFrameTab[3][3] PROGMEM = { { 384, 1152, 1152 }, /* MPEG1 */
{ 384, 1152, 576 }, /* MPEG2 */
{ 384, 1152, 576 }, /* MPEG2.5 */
};
/* layers 1, 2, 3 */
const short bitsPerSlotTab[3] = { 32, 8, 8 };
/* indexing = [version][mono/stereo]
* number of bytes in side info section of bitstream
*/
const int/*short*/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 int ISFIIP[2][2] PROGMEM = {
{0x40000000, 0x00000000}, /* mid-side off */
{0x40000000, 0x40000000}, /* mid-side on */
};
const unsigned char 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);
void MP3Decoder_FreeBuffers();
int MP3Decode( unsigned char *inbuf, int *bytesLeft, short *outbuf, int useSize);
void MP3GetLastFrameInfo();
int MP3GetNextFrameInfo(unsigned char *buf);
int MP3FindSyncWord(unsigned char *buf, int nBytes);
int MP3GetSampRate();
int MP3GetChannels();
int MP3GetBitsPerSample();
int MP3GetBitrate();
int MP3GetOutputSamps();
//internally used
void MP3Decoder_ClearBuffer(void);
void PolyphaseMono(short *pcm, int *vbuf, const uint32_t *coefBase);
void PolyphaseStereo(short *pcm, int *vbuf, const uint32_t *coefBase);
void SetBitstreamPointer(BitStreamInfo_t *bsi, int nBytes, unsigned char *buf);
unsigned int GetBits(BitStreamInfo_t *bsi, int nBits);
int CalcBitsUsed(BitStreamInfo_t *bsi, unsigned char *startBuf, int startOffset);
int DequantChannel(int *sampleBuf, int *workBuf, int *nonZeroBound, SideInfoSub_t *sis, ScaleFactorInfoSub_t *sfis, CriticalBandInfo_t *cbi);
void MidSideProc(int x[m_MAX_NCHAN][m_MAX_NSAMP], int nSamps, int mOut[2]);
void IntensityProcMPEG1(int x[m_MAX_NCHAN][m_MAX_NSAMP], int nSamps, ScaleFactorInfoSub_t *sfis, CriticalBandInfo_t *cbi, int midSideFlag, int mixFlag, int mOut[2]);
void IntensityProcMPEG2(int x[m_MAX_NCHAN][m_MAX_NSAMP], int nSamps, ScaleFactorInfoSub_t *sfis, CriticalBandInfo_t *cbi, ScaleFactorJS_t *sfjs, int midSideFlag, int mixFlag, int mOut[2]);
void FDCT32(int *x, int *d, int offset, int oddBlock, int gb);// __attribute__ ((section (".data")));
void FreeBuffers();
int CheckPadBit();
int UnpackFrameHeader(unsigned char *buf);
int UnpackSideInfo(unsigned char *buf);
int DecodeHuffman( unsigned char *buf, int *bitOffset, int huffBlockBits, int gr, int ch);
int MP3Dequantize( int gr);
int IMDCT( int gr, int ch);
int UnpackScaleFactors( unsigned char *buf, int *bitOffset, int bitsAvail, int gr, int ch);
int Subband(short *pcmBuf);
short ClipToShort(int x, int fracBits);
void RefillBitstreamCache(BitStreamInfo_t *bsi);
void UnpackSFMPEG1(BitStreamInfo_t *bsi, SideInfoSub_t *sis, ScaleFactorInfoSub_t *sfis, int *scfsi, int gr, ScaleFactorInfoSub_t *sfisGr0);
void UnpackSFMPEG2(BitStreamInfo_t *bsi, SideInfoSub_t *sis, ScaleFactorInfoSub_t *sfis, int gr, int ch, int modeExt, ScaleFactorJS_t *sfjs);
int MP3FindFreeSync(unsigned char *buf, unsigned char firstFH[4], int nBytes);
void MP3ClearBadFrame( short *outbuf);
int DecodeHuffmanPairs(int *xy, int nVals, int tabIdx, int bitsLeft, unsigned char *buf, int bitOffset);
int DecodeHuffmanQuads(int *vwxy, int nVals, int tabIdx, int bitsLeft, unsigned char *buf, int bitOffset);
int DequantBlock(int *inbuf, int *outbuf, int num, int scale);
void AntiAlias(int *x, int nBfly);
void WinPrevious(int *xPrev, int *xPrevWin, int btPrev);
int FreqInvertRescale(int *y, int *xPrev, int blockIdx, int es);
void idct9(int *x);
int IMDCT36(int *xCurr, int *xPrev, int *y, int btCurr, int btPrev, int blockIdx, int gb);
void imdct12(int *x, int *out);
int IMDCT12x3(int *xCurr, int *xPrev, int *y, int btPrev, int blockIdx, int gb);
int HybridTransform(int *xCurr, int *xPrev, int y[m_BLOCK_SIZE][m_NBANDS], SideInfoSub_t *sis, BlockCount_t *bc);
inline uint64_t SAR64(uint64_t x, int n) {return x >> n;}
inline int MULSHIFT32(int x, int y) { int z; z = (uint64_t) x * (uint64_t) y >> 32; return z;}
inline uint64_t MADD64(uint64_t sum64, int x, int y) {sum64 += (uint64_t) x * (uint64_t) y; return sum64;}/* returns 64-bit value in [edx:eax] */
inline uint64_t xSAR64(uint64_t x, int n){return x >> n;}
inline int FASTABS(int x){ return __builtin_abs(x);} //xtensa has a fast abs instruction //fb
#define CLZ(x) __builtin_clz(x) //fb