FAAC - ISO/MPEG 2/4 AAC Encoder Library

Contents

  • Scope
  • Interface description
  • API (faac.h)
  • Calling sequence
  • Error handling
  • Function reference
  • Porting from the legacy faacEnc* API
  • Scope

    This document describes the interface and usage of the FAAC - ISO/MPEG 2/4 AAC Encoder Library Developed for the Freeware Advanced Audio Coding project.

    Interface description

    The ISO/MPEG 2/4 AAC Encoder Library provides a high-level interface for encoding MPEG2 and MPEG4 ISO AAC files. A single header file is provided for usage in C/C++ programs:

    faac.h: the faac_* API — function prototypes and types.

    The encoder core resides in a statically linkable library called libfaac.lib (Microsoft Windows) or libfaac.a (UNIX). There are various example programs that show how to use the library.

    API (faac.h)

    The API supplies all encoder parameters once, up front, to faac_encoder_open(). The encoder therefore never exists in a half-configured state, and every derived quantity (frame size, output-buffer bound, effective sample rate, resolved object type) is known and queryable the instant open returns. Every fallible call returns a faac_status code; fixed-width integer types and width-pinned enums keep the ABI identical across platforms.
    Calling sequence
  • Zero-initialize a faac_params with faac_params_init(). This is mandatory — it stamps struct_size and clears padding, which is how the struct stays compatible as it grows in future releases.
  • Set the fields you care about (at minimum sample_rate and num_channels), then call faac_encoder_open().
  • Fill a faac_encoder_info with faac_encoder_get_info() (set its struct_size first) and size your buffers from it: input PCM holds info.frame_samples × num_channels samples; the output buffer must be at least info.max_output_bytes. The same struct also reports the resolved sample rate, object type, and rate-control settings. If you write a raw stream, fetch the AudioSpecificConfig with faac_encoder_asc() (library-owned — do not free it).
  • Call faac_encoder_encode() for each block of input; it emits at most one frame per call and reports the byte count via an out-parameter.
  • Pass in_samples == 0 to flush; keep calling until bytes_written is 0.
  • Call faac_encoder_close(), passing the address of your handle; it is set to NULL on success.
  • Error handling
    Every fallible entry point returns a faac_status. FAAC_OK is 0 and all error codes are negative, so status < 0 tests for failure. faac_strerror() maps any status to a static human-readable string (never NULL). Notable codes: FAAC_ERR_INVALID_ARGUMENT (NULL, bad struct_size, or an out-of-range field), FAAC_ERR_UNSUPPORTED (an object type this build does not implement, or a request with no ASC), FAAC_ERR_OUTPUT_TOO_SMALL, and FAAC_ERR_INPUT_OVERFLOW.
    Function reference
    /* library-global facts: compiled channel ceiling, version/copyright */
    faac_status faac_get_library_info(faac_library_info *out);
    
    faac_status faac_params_init(faac_params *p);
    faac_status faac_encoder_open(const faac_params *p, faac_encoder **out);
    faac_status faac_encoder_close(faac_encoder **enc);   /* sets *enc = NULL */
    
    /* resolved properties, valid after open; set out.struct_size first */
    faac_status faac_encoder_get_info(faac_encoder *enc, faac_encoder_info *out);
    
    /* AudioSpecificConfig: library-owned, valid until close, do NOT free */
    faac_status faac_encoder_asc(faac_encoder *enc, const uint8_t **buf, uint32_t *len);
    
    faac_status faac_encoder_encode(faac_encoder *enc,
                                    const void *in, uint32_t in_samples,
                                    uint8_t *out, uint32_t out_cap,
                                    uint32_t *bytes_written);
    
    const char *faac_strerror(faac_status status);
    
    The object_type field of faac_params uses MPEG-4 Audio Object Type numbers: FAAC_OBJ_LOW (2) is AAC-LC and FAAC_OBJ_HE_AAC_V1 (5) is HE-AAC v1 (AAC-LC core + SBR). FAAC_OBJ_AUTO (0) lets the library choose LC or HE-AAC from the bitrate. FAAC_OBJ_HE_AAC_V2 (29) is defined but not implemented; requesting it returns FAAC_ERR_UNSUPPORTED.

    For an HE-AAC encoder the SBR core runs at half the input rate and codes a 2048-sample frame, so faac_encoder_get_info() reports frame_samples == 2048 and sample_rate == the full (un-halved) output rate. Buffer sizing and rate reporting therefore stay correct without the caller knowing any SBR internals.

    Porting from the legacy faacEnc* API

    The classic faacEnc* surface (faacEncOpen, faacEncGetCurrentConfiguration/faacEncSetConfiguration, faacEncEncode, faacEncClose, faacEncGetVersion, faacEncGetDecoderSpecificInfo, and the faacEncConfiguration struct from faaccfg.h) has been removed. There is no compatibility shim — callers must move to faac_*. The changes are mechanical:
  • Open sequence. The old two-step open (faacEncOpen() to get a handle plus inputSamples/maxOutputBytes out-params, then faacEncGetCurrentConfiguration() / faacEncSetConfiguration() to apply options after the fact) collapses into one step: build a faac_params, fill in the fields you care about, and call faac_encoder_open() once. There is no live-pointer configuration struct to mutate after opening.
  • Buffer sizing. Where you previously read inputSamples and maxOutputBytes from faacEncOpen(), call faac_encoder_get_info() after faac_encoder_open() and use info.frame_samples × num_channels and info.max_output_bytes instead.
  • Version info. faacEncGetVersion() is replaced by faac_get_library_info(), which also reports max_channels; the removed name/copyright write-only config fields are gone along with it.
  • Decoder-specific info. faacEncGetDecoderSpecificInfo() is replaced by faac_encoder_asc(). The buffer is still library-owned and valid until close — do not free it.
  • Encoding loop. faacEncEncode() becomes faac_encoder_encode() with the byte count returned via an out-parameter (bytes_written) instead of the return value; the return value is now a faac_status. Flush and end-of-stream detection are unchanged: pass in_samples == 0 to flush, and keep calling until bytes_written is 0.
  • Close. faacEncClose(hEncoder) becomes faac_encoder_close(&enc) — pass the address of your handle, not the handle itself; the library NULLs it on success.
  • Return values. Where the old API returned NULL handles or -1 on error, every fallible faac_* call returns a faac_status; test status < 0 and use faac_strerror() for a message.
  • Configuration field renames. faacEncConfiguration fields map onto faac_params fields as follows:
  • aacObjectTypeobject_type (now uses FAAC_OBJ_* constants, numbered per the MPEG-4 AOT registry, rather than the old MAIN/LOW/SSR/LTP enum — MAIN, SSR, and LTP are retired, unimplemented object types).
  • mpegVersionmpeg_version (FAAC_MPEG4 / FAAC_MPEG2).
  • jointmodejoint_mode (FAAC_JOINT_*). allowMidside was a compatibility alias sharing storage with jointmode in a union; it has no separate replacement, use joint_mode directly.
  • useLfeuse_lfe; useTnsuse_tns (now bool).
  • shortctlshort_control (FAAC_SHORTCTL_*).
  • bitRatebit_rate; bandWidthbandwidth; quantqualquant_quality; pnslevelpns_level (same units and semantics).
  • outputFormatoutput_format (FAAC_STREAM_*); inputFormatinput_format (FAAC_INPUT_*).
  • channel_map[64]channel_map plus an explicit channel_map_count (the old fixed-size array was implicitly sized by numChannels).
  • version, name, and copyright were unused or library-populated informational fields in the legacy config struct; their closest analogs are faac_params.struct_size (for version-style compatibility checks) and faac_library_info.version/copyright (queried via faac_get_library_info()), not a faac_params field.
  • Struct growth. Always call faac_params_init() before setting any fields, and set struct_size on any struct you pass to a query function (faac_encoder_get_info(), faac_get_library_info()). This is how the ABI stays stable as these structs grow in later releases; the legacy config struct had no equivalent versioning.

  • FAAC is free software, licensed under the GNU Lesser General Public License (LGPL), version 2.1 or later.
    Copyright © 1999-2001, Menno Bakker · Copyright © 2002-2017, Krzysztof Nikiel · Copyright © 2004, Dan Villiom P. Christiansen · Copyright © 2005-2026, Fabian Greffrath · Copyright © 2026, Nils Schimmelmann