70 lines
2.5 KiB
C
70 lines
2.5 KiB
C
#pragma once
|
|
// mp3enc-filter.h
|
|
// Polyphase analysis filterbank: 32 new PCM samples in, 32 subband samples out.
|
|
// ISO 11172-3 clause 2.4.3.2 (encoder side, Annex C).
|
|
// Part of mp3enc. MIT license.
|
|
|
|
#include <cmath>
|
|
#include <cstring>
|
|
|
|
#ifndef M_PI
|
|
# define M_PI 3.14159265358979323846
|
|
#endif
|
|
// The analysis filterbank state for one channel.
|
|
// Holds the 512 sample FIFO and produces 32 subband outputs per call.
|
|
struct mp3enc_filter {
|
|
float buf[512]; // circular buffer of past PCM samples
|
|
int off; // current write offset into buf
|
|
|
|
void init() {
|
|
memset(buf, 0, sizeof(buf));
|
|
off = 0;
|
|
}
|
|
|
|
// Feed 32 new PCM samples, produce 32 subband samples.
|
|
// pcm: pointer to 32 float samples (mono, this channel only)
|
|
// sb_out: output array of 32 subband values
|
|
//
|
|
// Algorithm (ISO 11172-3 Annex C, encoding process):
|
|
// 1. Shift 32 new samples into the 512 sample FIFO
|
|
// 2. Window: multiply by 512 Ci coefficients (mp3enc_enwindow)
|
|
// 3. Partial sum: 512 windowed values -> 64 values
|
|
// 4. Matrixing: 64 values -> 32 subband samples via DCT
|
|
void process(const float * pcm, float * sb_out) {
|
|
// Step 1: shift new samples into the buffer.
|
|
// The newest sample goes at buf[off], oldest at buf[off+31].
|
|
// We store them in reverse order so windowing is a straight multiply.
|
|
off = (off - 32) & 511;
|
|
for (int i = 0; i < 32; i++) {
|
|
buf[(off + i) & 511] = pcm[31 - i];
|
|
}
|
|
|
|
// Step 2 + 3: window and partial sum.
|
|
// z[i] = sum over j=0..7 of: buf[(off + i + 64*j) & 511] * Ci[i + 64*j]
|
|
// This produces 64 values from the 512 windowed samples.
|
|
float z[64];
|
|
for (int i = 0; i < 64; i++) {
|
|
float sum = 0.0f;
|
|
for (int j = 0; j < 8; j++) {
|
|
int buf_idx = (off + i + 64 * j) & 511;
|
|
int win_idx = i + 64 * j;
|
|
sum += buf[buf_idx] * mp3enc_enwindow[win_idx];
|
|
}
|
|
z[i] = sum;
|
|
}
|
|
|
|
// Step 4: matrixing (ISO 11172-3, Annex C, analysis filter).
|
|
// sb_out[k] = sum over i=0..63 of: z[i] * cos((2*k + 1) * (16 - i) * PI / 64)
|
|
// for k = 0..31 (subbands)
|
|
// Formula verified against ISO 11172-3 Table C.1
|
|
for (int k = 0; k < 32; k++) {
|
|
float sum = 0.0f;
|
|
for (int i = 0; i < 64; i++) {
|
|
float angle = (float) M_PI * (float) (2 * k + 1) * (float) (16 - i) / 64.0f;
|
|
sum += z[i] * cosf(angle);
|
|
}
|
|
sb_out[k] = sum;
|
|
}
|
|
}
|
|
};
|