Projects
Essentials
faac
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 18
View file
_service:obs_scm:faac-1.40.obscpio/.github/workflows/master.yml -> _service:obs_scm:faac-1.50.obscpio/.github/workflows/master.yml
Changed
@@ -26,7 +26,6 @@ compiler: gcc, shell: bash, options: -Dfloating-point=double, - cflags: -Wall } - { name: Linux GCC (Single Precision), @@ -34,14 +33,12 @@ compiler: gcc, shell: bash, options: -Dfloating-point=single, - cflags: -Wall } - { name: macOS Clang, os: macos-latest, compiler: clang, shell: bash, - cflags: -Wall } - { name: MSYS2 UCRT64, @@ -50,7 +47,6 @@ shell: 'msys2 {0}', msystem: ucrt64, msys-env: mingw-w64-ucrt-x86_64, - cflags: -Wall } - { name: Windows MSVC, @@ -58,7 +54,6 @@ compiler: cl, shell: pwsh, options: -Dfloating-point=double, - cflags: /W4 } steps: @@ -77,7 +72,7 @@ - name: Install dependencies (MSYS2) if: matrix.config.shell == 'msys2 {0}' - uses: msys2/setup-msys2@v2.30.0 + uses: msys2/setup-msys2@v2.31.0 with: msystem: ${{ matrix.config.msystem }} update: false @@ -102,7 +97,6 @@ if: matrix.config.shell == 'msys2 {0}' env: CC: ${{ matrix.config.compiler }} - CFLAGS: ${{ matrix.config.cflags }} run: | mkdir -p build temp cd build @@ -113,7 +107,6 @@ if: matrix.config.shell != 'msys2 {0}' env: CC: ${{ matrix.config.compiler }} - CFLAGS: ${{ matrix.config.cflags }} run: | meson setup build -Dprefix="${{ github.workspace }}/temp" ${{ matrix.config.options }} meson install -C build
View file
_service:obs_scm:faac-1.40.obscpio/ChangeLog -> _service:obs_scm:faac-1.50.obscpio/ChangeLog
Changed
@@ -1,3 +1,31 @@ +1.50 (Apr 16, 2026) + + Fabian Greffrath + * Build quantize_sse library with hidden symbols + * Don't call `exit()` from the library + * Define some more `default_options` in Meson build + * Fix some warnings in `frontend/maingui.c` + * Default to `buildtype=release` in Meson build + * Initialize `data` variable in `huffcode()` + * Remove the faulty `HAVE_STRCASECMP` check and other pointless header checks + * CI: Let Meson build set `CFLAGS` + + Nils Schimmelmann + * Disallow PNS in MPEG-2 mode to match spec + * frontend: Change default to MPEG-4 as MPEG-2 is obsolete + * Add `max-channels` option to change `MAX_CHANNELS` from 64 + * Fix PNS to stay on in `JOINT_MS` for low-bitrate accuracy + * Replace redundant `cpe`, `sce`, and `lfe` boolean flags in `ChannelInfo` with an `enum` + * Reduce `MAX_CHANNELS` to 8 for ADTS compliance + * tns: Prevent division-by-zero or instability on highly correlated signals + * Implement MOS-optimized bandwidth calculation + * Fine-tune rate controller to restore bitrate accuracy + * Fix channel-specific group metadata in joint-stereo + * Enable link-time optimization (LTO) in Meson build + * stereo: Fix undefined behaviour in intensity stereo for degenerate bands + * Fix scalefactor delta overflows to comply with AAC spec (ISO 14496-3) + * quantize: Pre-clamp scalefactor deltas to fix encoder/decoder mismatch + 1.40 (Mar 17, 2026) tatsuz
View file
_service:obs_scm:faac-1.40.obscpio/TODO -> _service:obs_scm:faac-1.50.obscpio/TODO
Changed
@@ -6,3 +6,4 @@ - Add resampler and downmixer (hans-juergen, Oct 17, 2004) - Add HE AAC (hans-juergen, Oct 17, 2004) - Test TNS(arcen, Apr 8th, 2012) +- add PCE (Program Config Element) or 4-bit AudioSpecificConfig
View file
_service:obs_scm:faac-1.40.obscpio/frontend/input.h -> _service:obs_scm:faac-1.50.obscpio/frontend/input.h
Changed
@@ -28,9 +28,6 @@ #include <stdio.h> #include <stdlib.h> -#ifdef HAVE_SYS_TYPES_H -# include <sys/types.h> -#endif #include <stdint.h> #ifdef __cplusplus
View file
_service:obs_scm:faac-1.40.obscpio/frontend/main.c -> _service:obs_scm:faac-1.50.obscpio/frontend/main.c
Changed
@@ -38,7 +38,6 @@ #endif #ifdef __unix__ -#include <sys/time.h> #include <sys/resource.h> #include <unistd.h> #endif @@ -58,10 +57,6 @@ #include "mp4write.h" -#if !defined(HAVE_STRCASECMP) && !defined(_WIN32) -# define strcasecmp strcmp -#endif - #ifdef _WIN32 # undef stderr # define stderr stdout @@ -431,7 +426,7 @@ unsigned long samplesInput, maxBytesOutput, totalBytesWritten = 0; faacEncConfigurationPtr myFormat; - unsigned int mpegVersion = MPEG2; + unsigned int mpegVersion = MPEG4; unsigned int objectType = LOW; int jointmode = -1; int pnslevel = -1; @@ -936,6 +931,13 @@ myFormat->useLfe = 1; if (jointmode >= 0) myFormat->jointmode = jointmode; + + if (pnslevel > 0 && mpegVersion == MPEG2) + { + fprintf(stderr, "PNS not allowed in MPEG-2 mode, disabling PNS\n"); + pnslevel = 0; + } + if (pnslevel >= 0) myFormat->pnslevel = pnslevel; if (quantqual > 0)
View file
_service:obs_scm:faac-1.40.obscpio/frontend/maingui.c -> _service:obs_scm:faac-1.50.obscpio/frontend/maingui.c
Changed
@@ -105,6 +105,7 @@ SetDlgItemText (hWnd, IDC_INPUTFILENAME, inputFilename); strncpy(outputFilename, inputFilename, sizeof(outputFilename) - 5); + outputFilenamesizeof(outputFilename) - 5 = '\0'; pExt = strrchr(outputFilename, '.'); @@ -178,7 +179,7 @@ MessageBox (hWnd, "faacEncSetConfiguration failed!", "Error", MB_OK | MB_ICONSTOP); - SendMessage(hWnd,WM_SETTEXT,0,(long)"FAAC GUI"); + SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)"FAAC GUI"); Encoding = FALSE; SetDlgItemText(hWnd, IDOK, "Encode"); @@ -227,7 +228,7 @@ lstrcpy(HeaderText,"FAAC GUI: "); lstrcat(HeaderText,Percentage); lstrcat(HeaderText,"%"); - SendMessage(hWnd,WM_SETTEXT,0,(long)HeaderText); + SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)HeaderText); totalBytesRead += bytesInput; @@ -296,7 +297,7 @@ MessageBox(hWnd, "Couldn't open input file!", "Error", MB_OK | MB_ICONSTOP); } - SendMessage(hWnd,WM_SETTEXT,0,(long)"FAAC GUI"); + SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)"FAAC GUI"); Encoding = FALSE; SetDlgItemText(hWnd, IDOK, "Encode"); return 0;
View file
_service:obs_scm:faac-1.40.obscpio/frontend/mp4write.c -> _service:obs_scm:faac-1.50.obscpio/frontend/mp4write.c
Changed
@@ -23,14 +23,9 @@ #include <stdlib.h> #include <stdio.h> -#ifndef WORDS_BIGENDIAN -//#include <byteswap.h> -#endif #include <string.h> -#if !defined (_MSC_VER) -#include <sys/time.h> -#endif #include <time.h> + #ifdef _WIN32 #include <io.h> #define access _access
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/bitstream.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/bitstream.c
Changed
@@ -155,9 +155,9 @@ if (channelInfochannel.present) { /* Write out a single_channel_element */ - if (!channelInfochannel.cpe) { + if (channelInfochannel.type != ELEMENT_CPE) { - if (channelInfochannel.lfe) { + if (channelInfochannel.type == ELEMENT_LFE) { /* Write out lfe */ bits += WriteLFE(&coderInfochannel, &channelInfochannel, @@ -242,9 +242,9 @@ if (channelInfochannel.present) { /* Write out a single_channel_element */ - if (!channelInfochannel.cpe) { + if (channelInfochannel.type != ELEMENT_CPE) { - if (channelInfochannel.lfe) { + if (channelInfochannel.type == ELEMENT_LFE) { /* Write out lfe */ bits += WriteLFE(&coderInfochannel, &channelInfochannel,
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/blockswitch.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/blockswitch.c
Changed
@@ -246,7 +246,7 @@ if (channelInfochannel.present) { - if (channelInfochannel.cpe && + if (channelInfochannel.type == ELEMENT_CPE && channelInfochannel.ch_is_left) { /* CPE */ @@ -256,13 +256,12 @@ PsyCheckShort(&psyInfoleftChan, quality); PsyCheckShort(&psyInforightChan, quality); } - else if (!channelInfochannel.cpe && - channelInfochannel.lfe) + else if (channelInfochannel.type == ELEMENT_LFE) { /* LFE */ // Only set block type and it should be OK psyInfochannel.block_type = ONLY_LONG_WINDOW; } - else if (!channelInfochannel.cpe) + else if (channelInfochannel.type == ELEMENT_SCE) { /* SCE */ PsyCheckShort(&psyInfochannel, quality); }
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/channels.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/channels.c
Changed
@@ -65,8 +65,7 @@ if (numChannelsLeft != 2) { channelInfonumChannels-numChannelsLeft.present = 1; channelInfonumChannels-numChannelsLeft.tag = sceTag++; - channelInfonumChannels-numChannelsLeft.cpe = 0; - channelInfonumChannels-numChannelsLeft.lfe = 0; + channelInfonumChannels-numChannelsLeft.type = ELEMENT_SCE; numChannelsLeft--; } @@ -75,20 +74,18 @@ /* Left channel info */ channelInfonumChannels-numChannelsLeft.present = 1; channelInfonumChannels-numChannelsLeft.tag = cpeTag++; - channelInfonumChannels-numChannelsLeft.cpe = 1; channelInfonumChannels-numChannelsLeft.common_window = 0; channelInfonumChannels-numChannelsLeft.ch_is_left = 1; channelInfonumChannels-numChannelsLeft.paired_ch = numChannels-numChannelsLeft+1; - channelInfonumChannels-numChannelsLeft.lfe = 0; + channelInfonumChannels-numChannelsLeft.type = ELEMENT_CPE; numChannelsLeft--; /* Right channel info */ channelInfonumChannels-numChannelsLeft.present = 1; - channelInfonumChannels-numChannelsLeft.cpe = 1; channelInfonumChannels-numChannelsLeft.common_window = 0; channelInfonumChannels-numChannelsLeft.ch_is_left = 0; channelInfonumChannels-numChannelsLeft.paired_ch = numChannels-numChannelsLeft-1; - channelInfonumChannels-numChannelsLeft.lfe = 0; + channelInfonumChannels-numChannelsLeft.type = ELEMENT_CPE; numChannelsLeft--; } @@ -97,13 +94,11 @@ if (useLfe) { channelInfonumChannels-numChannelsLeft.present = 1; channelInfonumChannels-numChannelsLeft.tag = lfeTag++; - channelInfonumChannels-numChannelsLeft.cpe = 0; - channelInfonumChannels-numChannelsLeft.lfe = 1; + channelInfonumChannels-numChannelsLeft.type = ELEMENT_LFE; } else { channelInfonumChannels-numChannelsLeft.present = 1; channelInfonumChannels-numChannelsLeft.tag = sceTag++; - channelInfonumChannels-numChannelsLeft.cpe = 0; - channelInfonumChannels-numChannelsLeft.lfe = 0; + channelInfonumChannels-numChannelsLeft.type = ELEMENT_SCE; } numChannelsLeft--; }
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/channels.h -> _service:obs_scm:faac-1.50.obscpio/libfaac/channels.h
Changed
@@ -33,15 +33,19 @@ int ms_usedMAX_SCFAC_BANDS; } MSInfo; +typedef enum { + ELEMENT_SCE, + ELEMENT_CPE, + ELEMENT_LFE +} ElementType; + typedef struct { int tag; int present; int ch_is_left; int paired_ch; int common_window; - int cpe; - int sce; - int lfe; + ElementType type; MSInfo msInfo; } ChannelInfo;
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/coder.h -> _service:obs_scm:faac-1.50.obscpio/libfaac/coder.h
Changed
@@ -28,8 +28,6 @@ extern "C" { #endif /* __cplusplus */ -#define MAX_CHANNELS 64 - #define FRAME_LEN 1024 #define BLOCK_LEN_LONG 1024 #define BLOCK_LEN_SHORT 128
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/fft.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/fft.c
Changed
@@ -245,8 +245,9 @@ { if (logm > MAXLOGM) { - fprintf(stderr, "fft size too big\n"); - exit(1); + fprintf(stderr, "%s:%d: fft size too big (%d)\n", + __FILE__, __LINE__, logm); + return; } if (logm < 1) @@ -268,8 +269,9 @@ if (logm > MAXLOGR) { - fprintf(stderr, "rfft size too big\n"); - exit(1); + fprintf(stderr, "%s:%d: rfft size too big (%d)\n", + __FILE__, __LINE__, logm); + return; } memset(xi, 0, (1 << logm) * sizeof(xi0));
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/frame.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/frame.c
Changed
@@ -28,6 +28,7 @@ #include "channels.h" #include "bitstream.h" #include "filtbank.h" +#include "quantize.h" #include "util.h" #include "tns.h" #include "stereo.h" @@ -36,6 +37,10 @@ #include "win32_ver.h" #endif +/* Rate control tuning constants */ +#define RC_DEADBAND_THRESHOLD 0.05 /* +/- 5% deadband */ +#define RC_DAMPING_FACTOR 0.6 /* Control loop damping */ + static char *libfaacName = PACKAGE_VERSION; static char *libCopyright = "FAAC - Freeware Advanced Audio Coder (http://faac.sourceforge.net/)\n" @@ -50,11 +55,40 @@ static SR_INFO srInfo12+1; -// default bandwidth/samplerate ratio -static const struct { - faac_real fac; - faac_real freq; -} g_bw = {0.42, 18000}; +static unsigned int CalcBandwidth(unsigned long bitRate, unsigned long sampleRate) +{ + const unsigned int nyquist = sampleRate / 2; + unsigned int bw; + + if (!bitRate) return nyquist; + + if (bitRate <= 16000) { + /* Segment 1: Telephony (4kHz to 6kHz) */ + bw = 4000 + (bitRate / 8); + } + else if (bitRate <= 32000) { + /* Segment 2: Low-tier (6kHz to 11kHz) + */ + bw = 6000 + ((bitRate - 16000) * 5 / 16); + } + else if (bitRate <= 64000) { + /* Segment 3: Mid-tier expansion (11kHz to 18.5kHz) + */ + bw = 11000 + ((bitRate - 32000) * 15 / 64); + } + else if (bitRate <= 128000) { + /* Segment 4: High-fidelity catch-up (18.5kHz to 20kHz) */ + bw = 18500 + ((bitRate - 64000) * 3 / 128); + } + else { + /* Segment 5: Transparency plateau (20kHz+) */ + bw = 20000 + ((bitRate - 128000) / 16); + if (bw > 20000) bw = 20000; + } + + /* Safety clamp to Shannon-Nyquist limit */ + return (bw > nyquist) ? nyquist : bw; +} int FAACAPI faacEncGetVersion( char **faac_id_string, char **faac_copyright_string) @@ -158,15 +192,13 @@ if (config->bitRate && !config->bandWidth) { - config->bandWidth = (faac_real)config->bitRate * hEncoder->sampleRate * g_bw.fac / 50000.0; - if (config->bandWidth > g_bw.freq) - config->bandWidth = g_bw.freq; + config->bandWidth = CalcBandwidth(config->bitRate, hEncoder->sampleRate); if (!config->quantqual) { config->quantqual = (faac_real)config->bitRate * hEncoder->numChannels / 1280; - if (config->quantqual > 100) - config->quantqual = (config->quantqual - 100) * 3.0 + 100; + if (config->quantqual > DEFQUAL) + config->quantqual = (config->quantqual - DEFQUAL) * 3.0 + DEFQUAL; } } @@ -177,7 +209,7 @@ if (!config->bandWidth) { - config->bandWidth = g_bw.fac * hEncoder->sampleRate; + config->bandWidth = CalcBandwidth(config->bitRate, hEncoder->sampleRate); } hEncoder->config.bandWidth = config->bandWidth; @@ -195,7 +227,7 @@ hEncoder->config.quantqual = config->quantqual; - if (config->jointmode == JOINT_MS) + if (config->mpegVersion == MPEG2) config->pnslevel = 0; if (config->pnslevel < 0) config->pnslevel = 0; @@ -265,7 +297,7 @@ hEncoder->config.useLfe = 1; hEncoder->config.useTns = 0; hEncoder->config.bitRate = 64000; - hEncoder->config.bandWidth = g_bw.fac * hEncoder->sampleRate; + hEncoder->config.bandWidth = CalcBandwidth(hEncoder->config.bitRate, sampleRate); hEncoder->config.quantqual = 0; hEncoder->config.psymodellist = (psymodellist_t *)psymodellist; hEncoder->config.psymodelidx = 0; @@ -459,7 +491,7 @@ /* Psychoacoustics */ /* Update buffers and run FFT on new samples */ /* LFE psychoacoustic can run without it */ - if (!channelInfochannel.lfe || channelInfochannel.cpe) + if (channelInfochannel.type != ELEMENT_LFE) { hEncoder->psymodel->PsyBufferUpdate( &hEncoder->fft_tables, @@ -539,7 +571,7 @@ /* Perform TNS analysis and filtering */ for (channel = 0; channel < numChannels; channel++) { - if ((!channelInfochannel.lfe) && (useTns)) { + if ((channelInfochannel.type != ELEMENT_LFE) && (useTns)) { TnsEncode(&(coderInfochannel.tnsInfo), coderInfochannel.sfbn, coderInfochannel.sfbn, @@ -553,7 +585,7 @@ for (channel = 0; channel < numChannels; channel++) { // reduce LFE bandwidth - if (!channelInfochannel.cpe && channelInfochannel.lfe) + if (channelInfochannel.type == ELEMENT_LFE) { coderInfochannel.sfbn = 3; } @@ -571,7 +603,7 @@ for (channel = 0; channel < numChannels; channel++) { if (channelInfochannel.present - && (channelInfochannel.cpe) + && (channelInfochannel.type == ELEMENT_CPE) && (channelInfochannel.ch_is_left)) { CoderInfo *cil, *cir; @@ -598,22 +630,24 @@ / hEncoder->sampleRate; faac_real fix = (faac_real)desbits / (faac_real)(frameBytes * 8); - if (fix < 0.9) - fix += 0.1; - else if (fix > 1.1) - fix -= 0.1; - else + if (fix < (1.0 - RC_DEADBAND_THRESHOLD)) { + fix += RC_DEADBAND_THRESHOLD; + } else if (fix > (1.0 + RC_DEADBAND_THRESHOLD)) { + fix -= RC_DEADBAND_THRESHOLD; + } else { fix = 1.0; + } - fix = (fix - 1.0) * 0.5 + 1.0; + /* Apply damping to the quality adjustment */ + fix = (fix - 1.0) * RC_DAMPING_FACTOR + 1.0; // printf("q: %.1f(f:%.4f)\n", hEncoder->aacquantCfg.quality, fix); hEncoder->aacquantCfg.quality *= fix; if (hEncoder->aacquantCfg.quality > maxqual) hEncoder->aacquantCfg.quality = maxqual; - if (hEncoder->aacquantCfg.quality < 10) - hEncoder->aacquantCfg.quality = 10; + if (hEncoder->aacquantCfg.quality < MINQUAL) + hEncoder->aacquantCfg.quality = MINQUAL; } return frameBytes;
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/huff2.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/huff2.c
Changed
@@ -29,9 +29,9 @@ int preflen = 0; int base = 32; - if (x >= 8192) + if (x > MAX_HUFF_ESC_VAL) { - fprintf(stderr, "%s(%d): x_quant >= 8192\n", __FILE__, __LINE__); + fprintf(stderr, "%s(%d): x_quant > %d\n", __FILE__, __LINE__, MAX_HUFF_ESC_VAL); return 0; } @@ -67,7 +67,7 @@ int cnt; int bits = 0, blen; int ofs, *qp; - int data; + int data = 0; int idx; int datacnt; @@ -430,7 +430,7 @@ lastsf = coder->global_gain; lastis = 0; - lastpns = coder->global_gain - 90; + lastpns = coder->global_gain - SF_PNS_OFFSET; // fixme: move range check to quantizer for (cnt = 0; cnt < coder->bandcnt; cnt++) @@ -440,18 +440,15 @@ if ((book == HCB_INTENSITY) || (book== HCB_INTENSITY2)) { diff = coder->sfcnt - lastis; - if (diff > 60) - diff = 60; - if (diff < -60) - diff = -60; - length = book1260 + diff.len; + diff = clamp_sf_diff(diff); + length = book12SF_DELTA + diff.len; bits += length; lastis += diff; if (write) - PutBit(stream, book1260 + diff.data, length); + PutBit(stream, book12SF_DELTA + diff.data, length); } else if (book == HCB_PNS) { @@ -470,32 +467,26 @@ continue; } - if (diff > 60) - diff = 60; - if (diff < -60) - diff = -60; + diff = clamp_sf_diff(diff); - length = book1260 + diff.len; + length = book12SF_DELTA + diff.len; bits += length; lastpns += diff; if (write) - PutBit(stream, book1260 + diff.data, length); + PutBit(stream, book12SF_DELTA + diff.data, length); } - else if (book) + else if ((book != HCB_ZERO) && (book != HCB_NONE)) { diff = coder->sfcnt - lastsf; - if (diff > 60) - diff = 60; - if (diff < -60) - diff = -60; - length = book1260 + diff.len; + diff = clamp_sf_diff(diff); + length = book12SF_DELTA + diff.len; bits += length; lastsf += diff; if (write) - PutBit(stream, book1260 + diff.data, length); + PutBit(stream, book12SF_DELTA + diff.data, length); } }
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/huff2.h -> _service:obs_scm:faac-1.50.obscpio/libfaac/huff2.h
Changed
@@ -17,8 +17,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ****************************************************************************/ +#ifndef HUFF2_H +#define HUFF2_H + #include "bitstream.h" +/* Huffman Codebooks */ enum { HCB_ZERO = 0, HCB_ESC = 11, @@ -28,8 +32,39 @@ HCB_NONE }; +/* Maximum value representable by Huffman Book 11 escape sequences. + * Values >= 8192 would cause bitstream overflow/sync loss. */ +#define MAX_HUFF_ESC_VAL 8191 + +/* Scalefactor Management */ +enum { + /* Baseline scalefactor value used in bitstream */ + SF_OFFSET = 100, + /* Minimum allowable scalefactor to prevent underflow */ + SF_MIN = 10, + /* PNS predictor initialization offset (starts at floor) */ + SF_PNS_OFFSET = SF_OFFSET - SF_MIN, + /* Max allowed difference between successive scalefactors (AAC spec) */ + SF_DELTA = 60, +}; + +/** + * Restrict scalefactor delta to the spec-defined +/- SF_DELTA range. + * This ensures the delta remains valid for Book 12 Huffman encoding. + */ +static inline int clamp_sf_diff(int diff) +{ + if (diff > SF_DELTA) + return SF_DELTA; + if (diff < -SF_DELTA) + return -SF_DELTA; + return diff; +} + int huffbook(CoderInfo *coderInfo, int *qs /* quantized spectrum */, int len); int writebooks(CoderInfo *coder, BitStream *stream, int writeFlag); int writesf(CoderInfo *coder, BitStream *bitStream, int writeFlag); + +#endif /* HUFF2_H */
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/huffdata.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/huffdata.c
Changed
@@ -213,7 +213,7 @@ {5,4}, }; -hcode32_t book12121 = { +hcode32_t book122 * SF_DELTA + 1 = { {18,262120},{18,262118},{18,262119},{18,262117},{19,524277},{19,524273},{19,524269},{19,524278}, {19,524270},{19,524271},{19,524272},{19,524284},{19,524285},{19,524287},{19,524286},{19,524279}, {19,524280},{19,524283},{19,524281},{18,262116},{19,524282},{18,262115},{17,131055},{17,131056},
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/huffdata.h -> _service:obs_scm:faac-1.50.obscpio/libfaac/huffdata.h
Changed
@@ -15,6 +15,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ****************************************************************************/ +#ifndef HUFFDATA_H +#define HUFFDATA_H + +#include "huff2.h" + #include <stdint.h> typedef struct { @@ -38,4 +43,6 @@ extern hcode16_t book09169; extern hcode16_t book10169; extern hcode16_t book11289; -extern hcode32_t book12121; +extern hcode32_t book122 * SF_DELTA + 1; + +#endif /* HUFFDATA_H */
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/meson.build -> _service:obs_scm:faac-1.50.obscpio/libfaac/meson.build
Changed
@@ -11,7 +11,8 @@ sse2_flag = (cc.get_argument_syntax() == 'msvc') ? '/arch:SSE2' : '-msse2' quantize_sse = static_library('quantize_sse', 'quantize_sse.c', include_directories: '..', '../include', - c_args: c_args + sse2_flag + c_args: c_args + sse2_flag, + gnu_symbol_visibility: 'hidden' ) quantize_simd_libs += quantize_sse endif
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/quantize.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/quantize.c
Changed
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. ****************************************************************************/ +#include <limits.h> #include <math.h> #include <stdio.h> #include <stdlib.h> @@ -56,6 +57,11 @@ } static QuantizeFunc qfunc = quantize_scalar; +static faac_real sfstep; +static faac_real max_quant_limit; + +/* Sentinel: delta chain has no previous band yet (first active regular band). */ +#define SF_CHAIN_UNSET INT_MIN void QuantizeInit(void) { @@ -66,12 +72,34 @@ else #endif qfunc = quantize_scalar; + + /* 2^0.25 (1.50515 dB) step from AAC specs */ + sfstep = 1.0 / FAAC_LOG10(FAAC_SQRT(FAAC_SQRT(2.0))); + + /* Inverse-quantizer headroom: ensures (x * gain)^0.75 + 0.4054 <= 8191. + * Pre-calculated to avoid redundant runtime power functions. */ + max_quant_limit = FAAC_POW((faac_real)MAX_HUFF_ESC_VAL + 1.0 - MAGIC_NUMBER, 4.0/3.0); +} + +/* Compute gain from integer sfac, clamping against Huffman overflow. + * Updates *sfac if clamping was applied. Returns the usable gain. */ +static faac_real gain_with_overflow_clamp(int *sfac, faac_real band_peak) +{ + faac_real gain = FAAC_POW(10, *sfac / sfstep); + if (band_peak > 0.0 && gain * band_peak > max_quant_limit) + { + gain = max_quant_limit / band_peak; + *sfac = (int)FAAC_FLOOR(FAAC_LOG10(gain) * sfstep); + gain = FAAC_POW(10, *sfac / sfstep); + } + return gain; } + #define NOISEFLOOR 0.4 // band sound masking static void bmask(CoderInfo * __restrict coderInfo, faac_real * __restrict xr0, faac_real * __restrict bandqual, - faac_real * __restrict bandenrg, int gnum, faac_real quality) + faac_real * __restrict bandenrg, faac_real * __restrict bandmaxe, int gnum, faac_real quality) { int sfb, start, end, cnt; int *cb_offset = coderInfo->sfb_offset; @@ -130,6 +158,8 @@ } } bandenrgsfb = avge; + /* Track peak magnitude to identify potential Huffman overflows. */ + bandmaxesfb = FAAC_SQRT(maxe); maxe *= gsize; #define NOISETONE 0.2 @@ -166,24 +196,21 @@ const faac_real * __restrict xr0, const faac_real * __restrict bandqual, const faac_real * __restrict bandenrg, + const faac_real * __restrict bandmaxe, int gnum, - int pnslevel + int pnslevel, + int *p_last_abs /* previous active band's absolute stored scalefactor */ ) { int sb; -#if !defined(__clang__) && defined(__GNUC__) && (GCC_VERSION >= 40600) - /* 2^0.25 (1.50515 dB) step from AAC specs */ - static const faac_real sfstep = 1.0 / FAAC_LOG10(FAAC_SQRT(FAAC_SQRT(2.0))); -#else - static const faac_real sfstep = 20 / 1.50515; -#endif int gsize = coderInfo->groups.lengnum; faac_real pnsthr = 0.1 * pnslevel; - for (sb = 0; sb < coderInfo->sfbn; sb++) + for (sb = 0; sb < coderInfo->sfbn && coderInfo->bandcnt < MAX_SCFAC_BANDS; sb++) { faac_real sfacfix; int sfac; + int sf_rel; /* relative scalefactor index: SF_OFFSET - sfac */ faac_real rmsx; faac_real etot; int xitab8 * MAXSHORTBAND; @@ -220,10 +247,52 @@ } sfac = FAAC_LRINT(FAAC_LOG10(bandqualsb / rmsx) * sfstep); - if ((SF_OFFSET - sfac) < 10) + sf_rel = SF_OFFSET - sfac; + + /* sf_bias: IS intensity stereo energy offset pre-loaded into sf by + * AACstereo() before qlevel() runs; zero for regular bands. + * sf_abs = sf_bias + sf_rel is the value written to the bitstream. + * Delta chain comparisons must use sf_abs, not sf_rel alone. */ + int sf_bias = coderInfo->sfcoderInfo->bandcnt; + int sf_abs = sf_bias + sf_rel; + + if (sf_rel < SF_MIN) + { sfacfix = 0.0; + } else - sfacfix = FAAC_POW(10, sfac / sfstep); + { + /* Compute gain and clamp against Huffman overflow. */ + sfacfix = gain_with_overflow_clamp(&sfac, bandmaxesb); + sf_rel = SF_OFFSET - sfac; + sf_abs = sf_bias + sf_rel; + + /* Pre-clamp: enforce delta limits against the previous band's stored + * value so encoder and decoder use the same gain (sf_abs). */ + if (*p_last_abs != SF_CHAIN_UNSET) + { + int diff = sf_abs - *p_last_abs; + int clamped_diff = clamp_sf_diff(diff); + if (clamped_diff != diff) + { + sf_abs = *p_last_abs + clamped_diff; + sf_rel = sf_abs - sf_bias; + sfac = SF_OFFSET - sf_rel; + if (clamped_diff > 0) + { + /* Upward clamp raised gain; re-check Huffman overflow. */ + sfacfix = gain_with_overflow_clamp(&sfac, bandmaxesb); + sf_rel = SF_OFFSET - sfac; + sf_abs = sf_bias + sf_rel; + } + else + { + /* Downward clamp lowered gain; overflow impossible. */ + sfacfix = FAAC_POW(10, sfac / sfstep); + } + } + } + } end -= start; xi = xitab; @@ -241,7 +310,11 @@ } } huffbook(coderInfo, xitab, gsize * end); - coderInfo->sfcoderInfo->bandcnt++ += SF_OFFSET - sfac; + /* Track sf_abs (full bitstream value) for the next band's delta check. + * HCB_ZERO bands don't participate in the regular-band delta chain. */ + if (coderInfo->bookcoderInfo->bandcnt != HCB_ZERO) + *p_last_abs = sf_abs; + coderInfo->sfcoderInfo->bandcnt++ += sf_rel; } } @@ -249,6 +322,7 @@ { faac_real bandlvlMAX_SCFAC_BANDS; faac_real bandenrgMAX_SCFAC_BANDS; + faac_real bandmaxeMAX_SCFAC_BANDS; int cnt; faac_real *gxr; @@ -257,66 +331,52 @@ coder->bandcnt = 0; coder->datacnt = 0; + int lastsf = SF_CHAIN_UNSET; /* no previous band yet; first active band skips delta clamp */ + + gxr = xr; + for (cnt = 0; cnt < coder->groups.n; cnt++) { - int lastis; - int lastsf; + bmask(coder, gxr, bandlvl, bandenrg, bandmaxe, cnt, + (faac_real)aacquantCfg->quality/DEFQUAL); + qlevel(coder, gxr, bandlvl, bandenrg, bandmaxe, cnt, + aacquantCfg->pnslevel, &lastsf); + gxr += coder->groups.lencnt * BLOCK_LEN_SHORT; + } - gxr = xr; - for (cnt = 0; cnt < coder->groups.n; cnt++) + coder->global_gain = 0; + for (cnt = 0; cnt < coder->bandcnt; cnt++) + { + int book = coder->bookcnt; + if (!book) + continue; + if ((book != HCB_INTENSITY) && (book != HCB_INTENSITY2)) { - bmask(coder, gxr, bandlvl, bandenrg, cnt,
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/quantize.h -> _service:obs_scm:faac-1.50.obscpio/libfaac/quantize.h
Changed
@@ -44,7 +44,6 @@ MAXQUAL = 5000, MAXQUALADTS = MAXQUAL, MINQUAL = 10, - SF_OFFSET = 100, }; int BlocQuant(CoderInfo *coderInfo, faac_real *xr, AACQuantCfg *aacquantCfg);
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/stereo.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/stereo.c
Changed
@@ -83,6 +83,13 @@ ethr *= ethr; ethr *= phthr; efix = enrgl + enrgr; + /* Skip completely silent bands: efix==0 makes ethr==0 so IS would + * trigger spuriously, and vfix=sqrt(0/0) would be NaN. */ + if (efix <= 0.0) + { + (*sfcnt)++; + continue; + } if (enrgs >= ethr) { hcb = HCB_INTENSITY; @@ -96,6 +103,13 @@ if (hcb != HCB_NONE) { + /* If either channel is zero its log10 ratio is -inf; FAAC_LRINT + * on -inf is undefined behaviour. Skip to L/R coding instead. */ + if (enrgl == 0.0 || enrgr == 0.0) + { + (*sfcnt)++; + continue; + } int sf = FAAC_LRINT(FAAC_LOG10(enrgl / efix) * step); int pan = FAAC_LRINT(FAAC_LOG10(enrgr/efix) * step) - sf; @@ -327,7 +341,7 @@ if (!channelchn.present) continue; - if (!((channelchn.cpe) && (channelchn.ch_is_left))) + if (!((channelchn.type == ELEMENT_CPE) && (channelchn.ch_is_left))) continue; rch = channelchn.paired_ch; @@ -356,9 +370,9 @@ channelrch.msInfo.is_present = 1; } - for (group = 0; group < coder->groups.n; group++) + for (group = 0; group < coderchn.groups.n; group++) { - int end = start + coder->groups.lengroup; + int end = start + coderchn.groups.lengroup; switch(mode) { case JOINT_MS: midside(coder + chn, channel + chn, schn, srch, &sfcnt,
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/tns.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/tns.c
Changed
@@ -451,6 +451,10 @@ for (i=1;i<order;i++) { kTemp += aLastPtri*rArrayorder-i; } + if (error <= 0.0 || FAAC_FABS(kTemp) >= error) { + error = 0.0; + break; + } kTemp = -kTemp/error; kArrayorder=kTemp; aPtrorder=kTemp; @@ -458,12 +462,15 @@ aPtri = aLastPtri + kTemp*aLastPtrorder-i; } error = error * (1 - kTemp*kTemp); + if (error <= 0.0) break; /* Now make current iteration the last one */ aTemp=aLastPtr; aLastPtr=aPtr; /* Current becomes last */ aPtr=aTemp; /* Last becomes current */ } + /* If perfect prediction, trigger TNS */ + if (error <= 0.0) return DEF_TNS_GAIN_THRESH + 1.0; return signal/error; /* return the gain */ } }
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/util.c -> _service:obs_scm:faac-1.50.obscpio/libfaac/util.c
Changed
@@ -54,28 +54,3 @@ return 8000; } -/* Calculate bit_allocation based on PE */ -unsigned int BitAllocation(faac_real pe, int short_block) -{ - faac_real pew1; - faac_real pew2; - faac_real bit_allocation; - - if (short_block) { - pew1 = 0.6; - pew2 = 24.0; - } else { - pew1 = 0.3; - pew2 = 6.0; - } - bit_allocation = pew1 * pe + pew2 * FAAC_SQRT(pe); - bit_allocation = min(max(0.0, bit_allocation), 6144.0); - - return (unsigned int)(bit_allocation+0.5); -} - -/* Returns the maximum bit reservoir size */ -unsigned int MaxBitresSize(unsigned long bitRate, unsigned long sampleRate) -{ - return 6144 - (unsigned int)((faac_real)bitRate/(faac_real)sampleRate*(faac_real)FRAME_LEN); -}
View file
_service:obs_scm:faac-1.40.obscpio/libfaac/util.h -> _service:obs_scm:faac-1.50.obscpio/libfaac/util.h
Changed
@@ -50,8 +50,6 @@ int GetSRIndex(unsigned int sampleRate); unsigned int MaxBitrate(unsigned long sampleRate); unsigned int MinBitrate(); -unsigned int MaxBitresSize(unsigned long bitRate, unsigned long sampleRate); -unsigned int BitAllocation(faac_real pe, int short_block); #ifdef __cplusplus }
View file
_service:obs_scm:faac-1.40.obscpio/meson.build -> _service:obs_scm:faac-1.50.obscpio/meson.build
Changed
@@ -1,4 +1,12 @@ -project('faac', 'c', version: '1.40.0', default_options: 'default_library=both') +project('faac', 'c', + version: '1.50.0', + default_options: + 'default_library=both', + 'buildtype=release', + 'warning_level=1', + 'c_std=gnu99,c99', + 'b_lto=true' + ) add_global_arguments('-DHAVE_CONFIG_H', language: 'c') @@ -7,14 +15,11 @@ config_h.set_quoted('PACKAGE_VERSION', meson.project_version()) cc = meson.get_compiler('c') -foreach h: 'getopt.h', 'immintrin.h', 'stdint.h', 'sys/time.h', 'sys/types.h' +foreach h: 'getopt.h', 'immintrin.h' config_h.set('HAVE_' + h.underscorify().to_upper(), cc.has_header(h)) endforeach -config_h.set('HAVE_STRCASECMP', cc.has_function('strcasestr')) - - libm = cc.find_library('m', required: false) cpu_family = target_machine.cpu_family() @@ -27,6 +32,8 @@ config_h.set('FAAC_PRECISION_SINGLE', 1) endif +config_h.set('MAX_CHANNELS', get_option('max-channels')) + c_args = if cc.get_argument_syntax() == 'msvc' c_args += '-DWIN32', '-DNDEBUG', '-D_WINDOWS', '-D_USRDLL', '-DLIBFAAC_DLL_EXPORTS'
View file
_service:obs_scm:faac-1.40.obscpio/meson_options.txt -> _service:obs_scm:faac-1.50.obscpio/meson_options.txt
Changed
@@ -8,3 +8,10 @@ type: 'combo', choices: 'single', 'double', value: 'double') + +option('max-channels', + description: 'Maximum number of channels', + type: 'integer', + min: 1, + max: 8, + value: 8)
View file
_service:obs_scm:faac.obsinfo
Changed
@@ -1,4 +1,4 @@ name: faac -version: 1.40 -mtime: 1773730890 -commit: c899ee44ac1a0ca96c816e6c4d3de5a722d1cf56 +version: 1.50 +mtime: 1776322708 +commit: 79329efee51c9d3545bc4c7179b43a23fe350b6b
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.