LevelAPI2 & LevelShow2
Documentation
LevelAPI2 is a high-performance C dynamic library for loudness measurement and normalization to EBU R128 and ATSC A/85 (CALM Act) broadcast standards. This reference covers the full API, integration workflow, and all function signatures. LevelShow2, the bundled DirectShow filter for Windows pipelines, is documented in the second half.
01 Introduction
LevelAPI2 and LevelShow2 are built to support the transition from peak normalization to loudness normalization — one of the most significant changes in broadcast audio in decades. This shift began when the ITU published BS.1770 (LKFS/LUFS loudness metering) in 2006. The European Broadcast Union built on this foundation with EBU R128, released in 2010, which became the global broadcast loudness standard.
LevelAPI2 is the direct evolution of the software used by the EBU PLOUD working group during the creation of R128. It is maintained by tlemon.com.
The library interface consists entirely of C functions exposed through a dynamic library
(.dll on Windows, .so on Linux). This makes it callable from any
language with standard C FFI support — C, C++, Java, LUA, Python, Rust, Go, .NET, Delphi,
and others.
02 System Requirements
- Windows 7 or later (x86 / x64)
- Linux — built on CentOS 7 (x64); custom builds available for other distributions
- System memory: 512 MB minimum
- Disk space: approximately 10 MB
The Linux .so build depends on standard shared libraries:
libcurl.so.4, librt.so.1, libdl.so.2,
libpthread.so.0, libm.so.6, libc.so.6.
All are present in any standard CentOS 7 / RHEL / Fedora environment.
03 Upgrading from LevelAPI v1
If you are migrating from the original LevelAPI, note the following breaking changes:
Renamed functions
| v1 | v2 |
|---|---|
| Analyse() | AnalyseInterleaved() |
| Adjust() | AdjustInterleaved() |
| GetNeedLimiting() | GetLimitingNeeded() |
| GetLimitThresholddB() | GetLimiterThreshold() |
| SetNeedLimiting() | SetLimiterEnable() |
| SetLimiterThresholdEffective() | SetLimiterThresholdAdjust() |
| SetLimitThresholddB() | SetLimiterThreshold() |
| IsAdjustLevelLowered() | Removed — use GetLevel(AdjustLevel_NoPeak) vs GetLevel(AdjustLevel) |
Renamed enum values
| v1 | v2 |
|---|---|
| Max_M | LU_Max_M |
| Max_S | LU_Max_S |
| Max_M_FS | LUFS_Max_M |
| Max_S_FS | LUFS_Max_S |
| LRA_Low | LRA_Range_Low |
| LRA_High | LRA_Range_High |
| TruePeakHP / TruePeakLP | TruePeak (high precision only) |
| PSR_Min | PSR |
Behaviour changes
- All functions that return a boolean now return
1(true) on success and0(false) on failure — previously inconsistent. - PPM and RMS meters are disabled by default. Enable with
SetPPMEnable(true)andSetRMSEnable(true). - TruePeak HP and LP have been merged into a single high-precision
TruePeak.
04 Usage Guide
Implementing LevelAPI2 follows a consistent pattern regardless of language or platform. The steps below describe the complete workflow from loading the library to retrieving results.
-
Load the dynamic library at runtime
Use your platform's dynamic linking API (
dlopenon Linux,LoadLibraryon Windows) to load the library file. A helper macroLevelAPI2_LoadDLL(path, &handles)is provided in the header to retrieve all function pointers in one call. -
Validate your certificate
Call
SetCertificate(cert_string, length)as the first call after loading. This validates your license. If it returnsfalse, callGetErrorString()to retrieve the failure reason. The certificate string should be embedded or loaded from a secure location in your application. -
Create a handle
Call
Create_LevelAPI2(channels, samplerate, bitdepth)to create an instance. Every subsequent function call requires this handle as its first argument. You can create multiple handles to measure multiple sources simultaneously. Always callDestroy_LevelAPI2(handle)when done. -
Configure measurement standard
For EBU R128 compliance, call
SetPresetEBU_R128(handle). For ATSC A/85, callSetPresetATSC(handle). These convenience functions set calibration, gate, target type and level in one call. You can then override individual settings using the Advanced Settings functions if needed. -
Feed audio samples
Call
AnalyseInterleaved(handle, samples, numframes)with your interleaved float buffer. Thenumframesargument is in sample frames — for a stereo buffer of 512 samples,numframes = 256. For best performance, pass blocks of at least 256 frames. Maximum is16 × 1024 = 16384frames per call. For file-based workflows, useAnalyseFile(handle, filepath)directly. -
Read meter levels
At any point after analysis, call
GetLevel(handle, meterType, channel)using values from theMeterTypesenum. Pass-1as channel to get the combined result across all channels. Key values:LU,LRA,TruePeak,LU_Max_M,LU_Max_S. -
Normalize the audio
After analysis is complete, call
AdjustInterleaved(handle, samples, numframes)to apply gain correction to your sample buffer. If using the same handle for both steps, the required adjustment level is already known. If using a separate handle for adjustment, first callSetAdjustLevel(handle, dB)with the value fromGetAdjustLevel()orGetLevel(AdjustLevel). The built-in peak limiter activates automatically when needed.
Minimal C example
#include "LevelAPI2_dynlib.h" // 1. Load library struct LevelAPI2_FunctionHandles api; void* lib = LevelAPI2_LoadDLL(library_path, &api); // 2. Validate certificate api.SetCertificate(cert_string, strlen(cert_string)); // 3. Create handle LevelAPI2Ptr h = api.Create_LevelAPI2(channels, samplerate, bitdepth); // 4. Configure for EBU R128 api.SetPresetEBU_R128(h); // 5. Feed samples (interleaved float buffer) // numframes = total_samples / channels api.AnalyseInterleaved(h, samples, numframes); // 6. Read results float lu = api.GetLevel(h, LU, -1); float lra = api.GetLevel(h, LRA, -1); float truepeak = api.GetLevel(h, TruePeak, -1); // 7. Normalize api.AdjustInterleaved(h, samples, numframes); // Cleanup api.Destroy_LevelAPI2(h); LevelAPI2_UnloadDLL(lib);
05 Constants & Enums
DataRanges
| Constant | Value | Description |
|---|---|---|
| max_channels | 16 | Maximum number of audio channels |
| max_frames | 16384 | Maximum sample frames per AnalyseInterleaved call (16 × 1024) |
SurroundOrders
| Value | Channel Order |
|---|---|
| SMTPE_ITU_AC3 | L — R — C — Lfe — Ls — Rs |
| FilmDolbyDigital | L — C — R — Ls — Rs — Lfe |
| DTS_ProControl | L — R — Ls — Rs — C — Lfe |
MeterTypes
Used as the meterType argument in GetLevel() and related functions. Values marked (*) are generally for testing only and not intended for display to end users.
| Value | Description |
|---|---|
| LU | Integrated loudness — calibrated LU (gated) |
| LUFS | Integrated loudness — uncalibrated LUFS (gated) |
| LU_UNGATED | Calibrated LU without gating (*) |
| LUFS_UNGATED | Uncalibrated LUFS without gating (*) |
| LU_Min | Minimum calibrated LU level (*) |
| LU_Dialog | Calibrated dialog LU level (*) |
| LUFS_Dialog | Uncalibrated dialog LUFS level (*) |
| LU_Dialog_UNGATED | Dialog LU without gating (*) |
| Dialog_percentage | Percentage of dialog detected in the audio |
| LU_Max_M | Maximum momentary level (calibrated LU) |
| LUFS_Max_M | Maximum momentary level (uncalibrated LUFS) |
| LU_Max_S | Maximum short-term level, 3 s window (calibrated LU) |
| LUFS_Max_S | Maximum short-term level, 3 s window (uncalibrated LUFS) |
| LRA | Loudness range (LRA_High − LRA_Low) |
| LRA_Range_Low | Low boundary of the LRA calculation (*) |
| LRA_Range_High | High boundary of the LRA calculation (*) |
| LU_BS1771 | Realtime calibrated LU (BS.1771) (*) |
| LU_BS1771_Filtered | Realtime calibrated LU with meter filter |
| LU_BS1771_Shortterm | 3 s realtime calibrated LU |
| LUFS_BS1771_Shortterm | 3 s realtime uncalibrated LUFS (*) |
| PPM | Realtime PPM level (must be enabled) |
| PPM_Max | Maximum PPM value |
| RMS_Max | Maximum RMS value |
| Peak | Maximum sample peak (*) |
| TruePeak | Maximum true inter-sample peak |
| PSR | Peak-to-Short-term Ratio |
| PeakLoudness | PLR — Peak Loudness Range |
| Limited_dB | Amount of limiting applied in dB (*) |
| AdjustLevel | The calculated normalization gain in dB |
| AdjustLevel_NoPeak | Normalization gain ignoring peak limiting (*) |
06 Dynlib Initialization
These functions are called immediately after loading the dynamic library, before creating any handles.
Must be the first call made to the loaded library. Validates your license certificate. Returns true on success.
- arg 1Pointer to a char array containing the certificate text
- arg 2Total byte length of the certificate text (max 10 × 1024)
Call only when SetCertificate() has returned false. Fills the provided buffer with the error description.
- arg 1Pointer to an empty char array to receive the error text
- arg 2Size of the buffer (max 10 × 1024)
Creates and initializes a LevelAPI2 instance. Returns a valid handle, or NULL on failure. Every subsequent function call requires this handle as its first argument. Do not modify the returned value.
- channelsNumber of audio channels, e.g.
2for stereo - samplerateSample rate of the source material, e.g.
48000 - bitdepthBit depth used for dithering during gain adjustment —
16,24, or32
Releases all resources associated with the given handle. Must be called for every handle created with Create_LevelAPI2().
Returns the integer revision number of the loaded library binary. Useful for version checks at startup.
07 Library Initialization
Convenience preset for full EBU R128 compliance. Equivalent to calling: SetRelativeGate(−10), SetCalibration(LU, −23), SetAdjustTargetType(LU), SetAdjustTargetLevel(0).
Convenience preset for full ATSC A/85 (CALM Act) compliance. Equivalent to: SetRelativeGate(0), SetCalibration(LU, −24), SetAdjustTargetType(LU), SetAdjustTargetLevel(0).
You can combine presets with manual overrides. For example: call SetPresetEBU_R128() then SetCalibration() to override only the calibration value.
The following functions return stream format properties set during initialization:
Returns the number of channels.
Returns the sample rate.
08 Processing
Analyses a block of interleaved float samples. Call repeatedly to process a complete audio stream. For best performance, pass blocks of at least 256 frames.
- samplesPointer to an interleaved float buffer
- numframesNumber of sample frames (= total samples ÷ channels). Maximum:
16384
Non-interleaved variant. Use when your audio data is in separate channel buffers rather than interleaved.
Applies loudness normalization gain to the sample buffer in-place. Uses the AdjustLevel calculated by AnalyseInterleaved() (same handle), or the value set manually with SetAdjustLevel(). The peak limiter activates automatically when required.
- samplesPointer to the float buffer to be modified in-place
- numframesNumber of sample frames
Non-interleaved variant. Use when your audio data is in separate channel buffers rather than interleaved.
Analyses an audio file directly. Supported formats: WAV, AIFF, FLAC.
Normalizes an audio file and writes the result to a new file. The output path must not already exist.
- infilePath to the source audio file (WAV / AIFF / FLAC)
- outfilePath for the normalized output file (must not exist)
09 Results
Returns a meter value in dB for the given meter type and channel.
- meterTypeA value from the
MeterTypesenum — e.g.LU,LRA,TruePeak - channelChannel index (0-based), or
-1for the combined result across all channels
Returns the calculated normalization gain in dB. Use this to apply the gain manually, or save it for later use with a separate handle. Pass false (default) to include peak limiting in the calculation.
Manually sets the normalization gain in dB. Not needed when using the same handle for both analysis and adjustment. Use this when separating the analyse and adjust passes — for example, to analyse multiple files first, then adjust them in a second pass.
Returns the latency in samples introduced by the peak limiter during adjustment (approximately 20 ms). Account for this when synchronizing audio streams.
10 Advanced Settings
These functions modify measurement behaviour beyond the standard presets.
For straightforward EBU R128 or ATSC A/85 compliance, the preset functions are sufficient.
All Set functions return true on success.
Adjust Target
Returns the current target meter type used for normalization.
Sets the target meter type. Options: LU (default for R128/ATSC), PPM, or TruePeak.
Returns the target loudness level in dB.
Sets the normalization target level in dB. Default is 0 (0 LU = −23 LUFS for EBU, −24 LKFS for ATSC).
Channels
Returns the current surround channel order.
Sets the channel order for surround sources. Also automatically configures dialog channel detection. Use SMTPE_ITU_AC3, FilmDolbyDigital, or DTS_ProControl.
Overrides the per-channel weighting used for loudness measurement. Only relevant for surround configurations. SetSurroundOrder() handles this automatically for standard layouts.
- channelChannel index, 0 to
max_channels - weightWeight in dB
Gates
Returns the relative gate threshold in dB.
Sets the relative gate threshold. Default: −10 dB (EBU R128), 0 (ATSC — no gating).
Returns whether the dialog gate is enabled.
Enables or disables the dialog gate. Required for ATSC CALM Act compliance. The ATSC preset enables this automatically.
Calibration
Returns the calibration offset in dB for a given meter type.
Sets calibration offset. Defaults: −23 dB for EBU LU, −24 dB for ATSC. Meter type: LU, PPM, or TruePeak.
Limiter
Returns whether the limiter is active.
Forces the limiter on or off. By default it activates automatically when needed.
Returns the limiter analysis threshold in dBFS.
Sets the limiter threshold used during analysis. Default: −1.0 dBFS (prevents TruePeak clipping).
Returns the limiter threshold used during the adjustment pass.
Sets the limiter threshold for the adjustment pass. May differ from the analysis threshold because TruePeak and sample peak are not identical.
Time Window
Returns the current measurement window in seconds.
Limits the measurement to a rolling time window. Useful for continuous realtime metering. Each additional hour of window increases memory use by ~1.44 MB.
Legacy Meters (PPM / RMS)
PPM and RMS are legacy meters, disabled by default. Enable them only if your integration specifically requires them.
Enables or disables PPM measurement. Default: off.
Enables or disables RMS measurement. Default: off.
Histogram Access
Thread safety: Histogram functions are not thread-safe. Complete your read or copy before calling any other function on the same handle.
Raw histogram data is available for detailed loudness distribution analysis:
| Function | Returns |
|---|---|
| GetHistogramLUFS(handle, &size) | Integrated loudness histogram |
| GetHistogramLUFS_Dialog(handle, &size) | Dialog loudness histogram |
| GetHistogramLUFS_S(handle, &size) | Short-term loudness and LRA histogram |
| GetHistogramPSR(handle, &size) | Peak-to-Short-term Ratio histogram |
Conversion helpers between histogram positions and dB values:
Converts a LUFS value to a histogram array index.
Converts a histogram array index to a LUFS value.
Converts a dB value to a linear float.
Converts a linear float to dB.
11 Technical Specifications
EBU R128
ATSC A/85
Surround channel orders
| Mode | Channel order |
|---|---|
| SMPTE / ITU | L — R — C — Lfe — Ls — Rs |
| Film / Dolby | L — C — R — Ls — Rs — Lfe |
| DTS | L — R — Ls — Rs — C — Lfe |
12 LevelShow2 — Overview
LevelShow2 is a Windows DirectShow filter that wraps LevelAPI2 for use in Windows media pipeline applications. It is included with every LevelAPI2 license.
It exposes the same measurement and normalization capabilities as LevelAPI2 through
two interfaces: a graphical properties page for manual operation, and the
ILevelShow2 COM interface for programmatic control.
LevelShow2 is primarily relevant for Windows-based broadcast automation pipelines. For cross-platform or non-DirectShow use, LevelAPI2 directly is the correct integration path.
13 LevelShow2 — Usage
LevelShow2 can be implemented in two ways:
- Single instance — One filter handles both analysis and adjustment in sequence. Simpler workflow, suitable for most use cases.
- Two instances — One filter analyses, a second applies the adjustment. Allows analysing multiple files first, then normalizing them in a separate pass.
Basic workflow
-
1
Build your DirectShow graph
Connect your audio source to the LevelShow2 input pin and connect the output pin downstream.
-
2
Configure analysis settings
Enter your certificate, set Mode to Analyse, select your standard (EBU R128 or ATSC), and if using surround, select the correct channel order.
-
3
Stream the audio
Run the graph to pass all audio through the filter. LevelShow2 accumulates measurement data throughout the stream.
-
4
Switch to Adjust mode
Set Mode to Adjust. The filter automatically configures itself with the calculated normalization gain. To reset for a new stream, set Mode to
−1. -
5
Re-stream to apply normalization
Pass the audio through the filter again. The output is now level-normalized. Alternatively, pass the
AdjustLevelvalue to a second instance set to Adjust mode.
14 LevelShow2 — Programmatic Interface
Query the ILevelShow2 interface via IUnknown::QueryInterface
to control the filter programmatically. The interface mirrors the graphical controls exactly.
License
| Method | Description |
|---|---|
| put_Certificate(char*) | Supply your license certificate string |
| get_CertificateError(char*) | Retrieve error text if certificate is invalid |
| get_License(bool*) | Returns true if the current certificate is valid |
Mode
| Value | Meaning |
|---|---|
| 0 | Analyse mode |
| 1 | Adjust mode |
| −1 | Reset — clears measurement history and returns to Analyse |
Analyse settings
| Method | Values / Default | Description |
|---|---|---|
| put/get_MeasureType | 0=EBU R128, 1=ATSC, 2=Custom | Convenience preset — sets all related parameters |
| put/get_LURelativeGate | bool (true=on) | Enable/disable the −10 LU relative gate |
| put/get_DialogGate | bool (true=on) | Enable/disable dialog gate (ATSC CALM) |
| put/get_SurroundOrder | 0=SMPTE, 1=Film, 2=DTS | Surround channel order |
| put/get_CalibrationLU | float, default −23.00 | LU calibration offset in dB |
| put/get_CalibrationPPM | float, default −9.00 | PPM calibration offset in dB |
| put/get_MeterType | 0=LU, 1=PPM, 2=Peak | Target meter type for normalization |
| put/get_TargetLevel | float, default 0.00 | Target level in dB |
Results
| Method | Description |
|---|---|
| get_LULevel(float*) | Integrated loudness in LU |
| get_PPMLevel(float*) | PPM level |
| get_PeakLevel(float*) | True peak level |
| get_MaxMLevel(float*) | Maximum momentary level |
| get_MaxSLevel(float*) | Maximum short-term level |
| get_LRALevel(float*) | Loudness range |
| get_AdjustLevel(float*) | Calculated normalization gain in dB — use with put_AdjustLevel on a second instance |
| put_AdjustLevel(float) | Manually sets the adjustment gain — bypasses analysis |
| get_MLevel(float*) | Current momentary level (call per processed block for realtime metering) |
| get_SLevel(float*) | Current short-term level (call per processed block) |
| get_Warning(char*) | Returns a warning string if the adjust level is abnormal, NULL if none |
15 References
- tech.ebu.ch/loudness — EBU R128 recommendation, official documents, guidelines, and introduction videos
- ATSC A/85 Recommendation — available from the ATSC website
- ITU-R BS.1770 — the foundational loudness metering standard
A complete trial certificate and the header file (LevelAPI2_dynlib.h) are available on request. Contact us for licensing →