Skip to content

Commit 7a0d0e7

Browse files
author
Chris
committed
ultralight LPC very nearly lossless encoder
1 parent f4fa474 commit 7a0d0e7

7 files changed

Lines changed: 651 additions & 2 deletions

File tree

kitsune/codec/lpc.c

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
#include <stdio.h>
2+
#include <stdint.h>
3+
#include <limits.h>
4+
#include <math.h>
5+
6+
#include "lpc.h"
7+
8+
//Lookup Tables for 1st, 2nd and higher order quantized reflection coeffs
9+
static const int32_t
10+
lookup_1st_order_coeffs[128] =
11+
{-2147483648,-2147221504,-2146435072,-2145124352,-2143289344,-2140930048,-2138046464,-2134638592,-2130706432,-2126249984,-2121269248,-2115764224,-2109734912,-2103181312,-2096103424,-2088501248,-2080374784,-2071724032,-2062548992,-2052849664,-2042626048,-2031878144,-2020605952,-2008809472,-1996488704,-1983643648,-1970274304,-1956380672,-1941962752,-1927020544,-1911554048,-1895563264,-1879048192,-1862008832,-1844445184,-1826357248,-1807745024,-1788608512,-1768947712,-1748762624,-1728053248,-1706819584,-1685061632,-1662779392,-1639972864,-1616642048,-1592786944,-1568407552,-1543503872,-1518075904,-1492123648,-1465647104,-1438646272,1411121152,-1383071744,-1354498048,-1325400064,-1295777792,-1265631232,-1234960384,-1203765248,-1172045824,-1139802112,-1107034112,-1073741824,-1039925248,-1005584384,-970719232,-935329792,-899416064,-862978048,-826015744,-788529152,-750518272,-711983104,-672923648,-633339904,-593231872,-552599552,-511442944,-469762048,-427556864,-384827392,-341573632,-297795584,-253493248,-208666624,-163315712,-117440512,-71041024,-24117248,23330816,71303168,119799808,168820736,218365952,268435456,319029248,370147328,421789696,473956352,526647296,579862528,633602048,687865856,742653952,797966336,853803008,910163968,967049216,1024458752,1082392576,1140850688,1199833088,1259339776,1319370752,1379926016,1441005568,1502609408,1564737536,1627389952,1690566656,1754267648,1818492928,1883242496,1948516352,2014314496,2080636928};
12+
13+
/*Checks if every sample of a block is equal or not*/
14+
int32_t check_if_constant(const int16_t *data,int32_t num_elements)
15+
{
16+
int16_t temp = data[0];
17+
int i;
18+
19+
for( i = 1; i < num_elements; i++)
20+
{
21+
if(temp != data[i])
22+
return -1;
23+
}
24+
25+
return 0;
26+
}
27+
28+
/*autocorrelation function*/
29+
void auto_corr_fun(int32_t *x,int32_t N,int64_t k,int16_t norm,int32_t *rxx)
30+
{
31+
int64_t i, n;
32+
int32_t sum = 0,mean = 0;
33+
34+
for (i = 0; i < N; i++)
35+
sum += x[i];
36+
mean = sum/N;
37+
38+
for(i = 0; i <= k; i++)
39+
{
40+
rxx[i] = 0.0;
41+
for (n = i; n < N; n++)
42+
rxx[i] += ((int64_t)(x[n] - mean) * (x[n-i] - mean))>>15;
43+
}
44+
45+
if(norm)
46+
{
47+
for (i = 1; i <= k; i++)
48+
rxx[i] /= rxx[0];
49+
rxx[0] = 1<<15;
50+
}
51+
52+
return;
53+
}
54+
55+
/*Levinson recursion algorithm*/
56+
void levinson(int32_t *autoc,uint8_t max_order,int32_t *ref,int32_t lpc[][MAX_LPC_ORDER])
57+
{
58+
int32_t i, j, i2;
59+
int32_t r, err, tmp;
60+
int32_t lpc_tmp[MAX_LPC_ORDER];
61+
62+
for(i = 0; i < max_order; i++)
63+
lpc_tmp[i] = 0;
64+
err = 1.0;
65+
if(autoc)
66+
err = autoc[0];
67+
68+
for(i = 0; i < max_order; i++)
69+
{
70+
if(ref)
71+
r = ref[i];
72+
else
73+
{
74+
r = -autoc[i+1];
75+
for(j = 0; j < i; j++)
76+
r -= lpc_tmp[j] * autoc[i-j];
77+
r /= err;
78+
err *= 1.0 - (r * r);
79+
}
80+
81+
i2 = i >> 1;
82+
lpc_tmp[i] = r;
83+
for(j = 0; j < i2; j++)
84+
{
85+
tmp = lpc_tmp[j];
86+
lpc_tmp[j] += r * lpc_tmp[i-1-j];
87+
lpc_tmp[i-1-j] += r * tmp;
88+
}
89+
if(i & 1)
90+
lpc_tmp[j] += lpc_tmp[j] * r;
91+
92+
for(j = 0; j <= i; j++)
93+
lpc[i][j] = -lpc_tmp[j];
94+
}
95+
96+
return;
97+
}
98+
99+
/*Calculate reflection coefficients*/
100+
uint8_t compute_ref_coefs(int32_t *autoc,uint8_t max_order,int32_t *ref)
101+
{
102+
int32_t i, j;
103+
int32_t error;
104+
int32_t gen[2][MAX_LPC_ORDER];
105+
uint8_t order_est;
106+
107+
//Schurr recursion
108+
for(i = 0; i < max_order; i++)
109+
gen[0][i] = gen[1][i] = autoc[i+1];
110+
111+
error = autoc[0];
112+
ref[0] = ((int64_t)-gen[1][0]<<15) / error;
113+
error += ((int64_t)gen[1][0] * ref[0] ) >> 15;
114+
for(i = 1; i < max_order; i++)
115+
{
116+
for(j = 0; j < max_order - i; j++)
117+
{
118+
gen[1][j] = gen[1][j+1] + (int64_t)ref[i-1] * gen[0][j] >> 15;
119+
gen[0][j] = (int64_t)gen[1][j+1] * ref[i-1] >> 15 + gen[0][j];
120+
}
121+
ref[i] = ((int64_t)-gen[1][0]<<15) / error;
122+
error += ((int64_t)gen[1][0] * ref[i])>>15;
123+
}
124+
125+
//Estimate optimal order using reflection coefficients
126+
order_est = 1;
127+
for(i = max_order - 1; i >= 0; i--)
128+
{
129+
if(abs(ref[i]) > 0.05*(1<<15))
130+
{
131+
order_est = i+1;
132+
break;
133+
}
134+
}
135+
136+
return(order_est);
137+
}
138+
139+
static int32_t fastsqrt( int32_t x ) {
140+
int64_t s = x;
141+
x = 20000u;
142+
x = ( x + s / x )/2;
143+
x = ( x + s / x )/2;
144+
x = ( x + s / x )/2;
145+
x = ( x + s / x )/2;
146+
return x;
147+
}
148+
149+
/*Quantize reflection coeffs*/
150+
int32_t qtz_ref_cof(int32_t *par,uint8_t ord,int32_t *q_ref)
151+
{
152+
int i;
153+
for( i = 0; i < ord; i++)
154+
{
155+
if(i == 0)
156+
q_ref[i] = (( ((SQRT2 * fastsqrt(par[i] + 1)) >> 15) - (1<<15) )) >> 9;
157+
}
158+
159+
return(0);
160+
}
161+
162+
/*Dequantize reflection coefficients*/
163+
int32_t dqtz_ref_cof(const int32_t *q_ref,uint8_t ord,int32_t *ref)
164+
{
165+
int i;
166+
167+
if(ord <= 1)
168+
{
169+
ref[0] = 0;
170+
return(0);
171+
}
172+
173+
for( i = 0; i < ord; i++)
174+
{
175+
if(i == 0)
176+
ref[i] = lookup_1st_order_coeffs[q_ref[i] + 64];
177+
}
178+
179+
return(0);
180+
}
181+
182+
/*Calculate residues from samples and lpc coefficients*/
183+
void calc_residue(const int32_t *samples,int64_t N,int16_t ord,int16_t Q,int64_t *coff,int32_t *residues)
184+
{
185+
int64_t k, i;
186+
int64_t corr;
187+
int64_t y;
188+
189+
corr = ((int64_t)1) << (Q - 1);//Correction term
190+
191+
residues[0] = samples[0];
192+
for(k = 1; k <= ord; k++)
193+
{
194+
y = corr;
195+
for(i = 1; i <= k; i++)
196+
{
197+
y += (int64_t)coff[i] * samples[k-i];
198+
if((k - i) == 0)
199+
break;
200+
}
201+
residues[k] = samples[k] - (int32_t)(y >> Q);
202+
}
203+
204+
for(k = ord + 1; k < N; k++)
205+
{
206+
y = corr;
207+
208+
for(i = 0; i <= ord; i++)
209+
y += (int64_t)(coff[i] * samples[k-i]);
210+
residues[k] = samples[k] - (int32_t)(y >> Q);
211+
}
212+
213+
return;
214+
}
215+
216+
/*Calculate samples from residues and lpc coefficients*/
217+
void calc_signal(const int32_t *residues,int64_t N,int16_t ord,int16_t Q,int64_t *coff,int32_t *samples)
218+
{
219+
int64_t k, i;
220+
int64_t corr;
221+
int64_t y;
222+
223+
corr = ((int64_t)1) << (Q - 1);//Correction term
224+
225+
samples[0] = residues[0];
226+
for(k = 1; k <= ord; k++)
227+
{
228+
y = corr;
229+
for(i = 1; i <= k; i++)
230+
{
231+
y -= (int64_t)(coff[i] * samples[k-i]);
232+
if((k - i) == 0)
233+
break;
234+
}
235+
samples[k] = residues[k] - (int32_t)(y >> Q);
236+
}
237+
238+
for(k = ord + 1; k < N; k++)
239+
{
240+
y = corr;
241+
242+
for(i = 0; i <= ord; i++)
243+
y -= (int64_t)(coff[i] * samples[k-i]);
244+
samples[k] = residues[k] - (int32_t)(y >> Q);
245+
}
246+
247+
return;
248+
}

kitsune/codec/lpc.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef _LPC_H_
2+
#define _LPC_H_
3+
4+
#define SQRT2 46340
5+
//1.4142135623730950488016887242096
6+
#define MAX_LPC_ORDER 1
7+
8+
int32_t check_if_constant(const int16_t *data,int32_t num_elements);
9+
void auto_corr_fun(int32_t *x,int32_t N,int64_t k,int16_t norm,int32_t *rxx);
10+
void levinson(int32_t *autoc,uint8_t max_order,int32_t *ref,int32_t lpc[][MAX_LPC_ORDER]);
11+
uint8_t compute_ref_coefs(int32_t *autoc,uint8_t max_order,int32_t *ref);
12+
int32_t qtz_ref_cof(int32_t *par,uint8_t ord,int32_t *q_ref);
13+
int32_t dqtz_ref_cof(const int32_t *q_ref,uint8_t ord,int32_t *ref);
14+
void calc_residue(const int32_t *samples,int64_t N,int16_t ord,int16_t Q,int64_t *coff,int32_t *residues);
15+
void calc_signal(const int32_t *residues,int64_t N,int16_t ord,int16_t Q,int64_t *coff,int32_t *samples);
16+
17+
#endif

0 commit comments

Comments
 (0)