CS 307 · Artificial Intelligence · Paper implementation

APCodec: shrinking audio by teaching a network to describe sound twice.

A plain-language tour of a neural audio codec that encodes the amplitude and the phase of sound in parallel, squeezes them into a few numbers per moment, and rebuilds the audio on the other side.

Paper: Y. Ai, X.-H. Jiang, Y.-X. Lu, H.-P. Du, Z.-H. Ling, IEEE/ACM Trans. Audio, Speech, and Language Processing, vol. 32, pp. 3256–3269, 2024 · arXiv 2402.10533
Implemented by Devanshi Tiwari, Rajveer Chaudhari, Shubhankar Verma · IIIT Vadodara
48 kHz audio6 kbps128× smaller than raw6.67 ms latency5.8× real-time on one CPU core
01 · The problem

What is an audio codec, and why build a new one?

A codec is a pair of programs: an encoder that turns sound into as few bits as possible, and a decoder that turns those bits back into sound that should be indistinguishable from the original.

768 kbps

One second of raw 48 kHz, 16-bit audio: 48,000 samples × 16 bits.

6 kbps

What APCodec needs for the same second, with almost no audible loss.

128×

Compression. A 3-minute voice note goes from ~17 MB to ~135 KB.

Two old families, each with a weakness

Parametric codecs · LPC, Opus, EVS

Describe the sound

Send a short recipe (pitch, loudness, timbre) and let the receiver re-synthesise it. Very few bits, but the result sounds robotic and breaks down with noise.

Waveform codecs · PCM, SoundStream, Encodec, DAC

Copy the wave

Reproduce the wave shape itself. High quality, but it needs many bits, or (for neural ones) hundreds of downsampling steps that make the model large and slow.

APCodec's idea: the best of both

Treat the amplitude spectrum and the phase spectrum as the "parameters" of the sound, like a parametric codec does, but train the network with losses that demand a faithful waveform, like a waveform codec does. Because spectra already run at a low frame rate, only 8× downsampling is needed instead of 320×.

02 · Background

Any sound = how loud each pitch is + where each wave is in its cycle

Cut audio into tiny overlapping slices (the short-time Fourier transform, STFT). For every slice and every frequency you get two numbers.

Waveform x → STFT Amplitude spectrum A (how loud) Phase spectrum P (where in the cycle)
Left: a short piece of speech. Right: every column is one 6.7 ms slice, every row is one frequency. Amplitude is easy for a network to learn; phase wraps around at ±π and looks like noise, which is why most codecs ignore it. APCodec models it explicitly.

Amplitude A

The energy at each frequency. It shapes what we hear as vowels, timbre and loudness. Stored as a log value so quiet details are not lost.

Phase P

The timing offset of each frequency's wave. Get it wrong and audio sounds "phasey", metallic or smeared. Together, A and P rebuild the exact waveform through the inverse STFT.

03 · Architecture

Encoder → quantizer → decoder, with two lanes the whole way

Amplitude and phase travel through identical, parallel networks. They merge into one compact code in the middle and split again to be rebuilt.

Audio48 kHz STFT Amplitude encoderConv · 8× ConvNeXt v2 · ↓8 Phase encoderConv · 8× ConvNeXt v2 · ↓8 concat→ 32 dims Residual VQQ codebooks1024 entries 010110… bits split Amplitude decoder↑8 · 8× ConvNeXt v2 → Â Phase decoder↑8 · ConvNeXt v2 → R, I → atan2 e^Â · e^{jP̂} → ISTFT → audio ENCODER QUANTIZER DECODER
Based on Fig. 1 of the paper. Frame rates at 48 kHz: spectra at 1.2 kHz (hop of 40 samples), latent code at 150 Hz after 8× downsampling.

ConvNeXt v2 blocks

An image-recognition backbone turned 1-D: depth-wise conv → LayerNorm → expand to 512 → GELU → GRN → back to 256, plus a residual shortcut. Eight per lane.

Only 8× downsampling

Waveform codecs shrink 48,000 samples/s by 320×. APCodec starts from 1,200 spectrum frames/s, so 8× is enough to reach 150 codes/s. Fewer layers means a faster, smaller model.

Smart phase output

The phase lane predicts a "real" part R and an "imaginary" part I, then takes atan2(I, R). The answer is always a valid angle, so the network never fights phase wrapping.

04 · Where the bits come from

Residual vector quantization: guess, then correct the guess

Every 6.67 ms the encoder outputs a 32-number vector. Sending 32 floats would be costly, so instead we send which entry of a 1024-word codebook it is closest to: just 10 bits.

true vector

Codebook 1

Pick the closest of 1024 learned vectors. Rough, but already in the right area.

Codebook 2

Look at what's left over (the residual) and pick the best correction from a second codebook.

…Codebook Q

Repeat. Each stage fixes the previous one's error. The receiver adds the Q chosen vectors back up.

Bitrate = fs / (hop × D) × Q × log₂M = 48000 / (40 × 8) × 4 × 10 = 6,000 bit/s

With Q = 4 codebooks the paper gets 6 kbps, and with Q = 8 it gets 12 kbps. More codebooks means more corrections, so better quality for more bits.

05 · Training

Four kinds of "you got it wrong" signals

The encoder, quantizer and decoder are trained together as one network. The loss is a sum of several terms, each catching a different kind of mistake.

Spectral

Amplitude MSE, phase anti-wrapping losses (instantaneous phase, group delay, angular frequency), complex spectrum + STFT consistency, and mel spectrogram L1+L2.

Quantization

Pulls the encoder's output and the codebook entries towards each other, so little is lost when snapping to the nearest codeword.

Adversarial (GAN)

Two critics, multi-period (MPD) and multi-resolution (MRD), try to tell real audio from decoded audio. The codec learns to fool them, which removes buzzy artefacts.

Feature matching

The decoded audio should also look like the real audio inside the critics' layers, not just at their final verdict.

fAW(x) = | x − 2π · round(x / 2π) | // a phase error of 359° counts as 1°, not 359°

That anti-wrapping trick is the key to learning phase at all. Without it, a prediction of +179° against a target of −179° would look like a huge error when it is really only 2° off.

06 · Real-time use

APCodec-S: streaming with a teacher

For phone calls the codec can't wait for the future. The streaming version swaps layers that look ahead for ones that only look back, then learns from the full model.

Causal layers

Look-ahead convolutions become feed-forward layers, upsampling becomes causal, and the downsampling kernel is kept ≤ 2D−1 so no future frame is needed.

Knowledge distillation

The non-streaming APCodec acts as the teacher. The streaming student is trained to match the teacher's internal features layer by layer (MSE).

6.67 ms

Fixed latency at 48 kHz: one code frame (320 samples). That's far below the ~150 ms where calls start to feel laggy.

07 · Results from the paper

Better sound, faster, and smaller

VCTK test set, 48 kHz audio at 6 kbps (Tables I and II of the paper).

Overall quality: ViSQOL (higher is better, max 4.75)

APCodec
4.07
AudioDec
3.98
APCodec-S
3.93
DAC
3.81
Encodec
3.31

Speed on one CPU core: × real-time (higher is better)

APCodec-S
8.93×
APCodec
5.78×
Encodec
4.31×
AudioDec
1.30×
DAC
0.41×

Full comparison at 48 kHz, 6 kbps

CodecStreamableLSD ↓STOI ↑ViSQOL ↑Phase error AWPDIP ↓Size ↓MUSHRA ↑
APCodecNo0.8180.8754.071.6865.4M88.48
APCodec-SYes0.8350.8653.931.7446.8M88.07
EncodecYes1.040.7933.311.8083.2M85.91
AudioDecYes0.8470.8043.981.81108M88.34
DACNo0.8410.9063.811.78282M88.28

Phase really helps

Every other codec sits near 1.80 rad of phase error. Modelling phase explicitly brings APCodec down to 1.68.

4.3× smaller than DAC

65 M parameters versus 282 M, and about 14× faster on CPU, where DAC can't even keep up with real time.

Every piece matters

Ablations: swapping ConvNeXt v2 for a plain residual net drops ViSQOL by 0.5; removing the quantization loss drops it by 0.33.

08 · Our implementation

What we built and run here

We use the authors' open-source model code (encoder, residual VQ, decoder, discriminators and losses) with our own training and serving pipeline.

Data

LibriSpeech

train-clean-100: 100 h, 251 speakers. Test clips come from unseen test-clean speakers.

Config

16 kHz · D = 8

The paper's 16 kHz setup: hop 40, window 320, FFT 1024, latent at 50 Hz.

Bitrate

0.5–4 kbps

8 codebooks × 1024 with quantizer dropout, so one model can serve every bitrate. The paper uses 2 and 4 kbps at 16 kHz.

Hardware

CPU only

Trained on a 16-core Xeon with spectral, phase, mel and quantization losses. The paper used 1 M GPU steps with GAN losses.

Checking model…

The model is still training. The demo below always uses the newest checkpoint, so expect quality to improve over time. An early checkpoint is intelligible but less clean than the paper's fully trained model.

09 · Live demo

Compress your own audio

Upload a clip (up to 20 s) or record from your mic. The server runs the real APCodec encoder, shows the discrete tokens it would transmit, then decodes them back to audio.

Drop an audio file here or click to chooseWAV, MP3, FLAC, OGG, M4A
Or use a sample:
Codebooks used: 8 of 84.0 kbps
Fewer codebooks means fewer bits and rougher sound. That's residual VQ in action.
No audio chosen
loadSTFTencode A + PRVQ → tokensdecodeISTFT