2009-08-22 22:13:03 +00:00
|
|
|
/**
|
|
|
|
|
* CUETools.Flake: pure managed FLAC audio encoder
|
|
|
|
|
* Copyright (c) 2009 Gregory S. Chudov
|
|
|
|
|
* Based on Flake encoder, http://flake-enc.sourceforge.net/
|
|
|
|
|
* Copyright (c) 2006-2009 Justin Ruggles
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
*/
|
|
|
|
|
|
2009-08-17 03:39:53 +00:00
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace CUETools.Codecs.FLAKE
|
|
|
|
|
{
|
|
|
|
|
class lpc
|
|
|
|
|
{
|
|
|
|
|
public const int MAX_LPC_ORDER = 32;
|
|
|
|
|
public const int MAX_LPC_WINDOWS = 4;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Apply Welch window function to audio block
|
|
|
|
|
*/
|
|
|
|
|
static unsafe void
|
|
|
|
|
apply_welch_window(/*const*/int* data, uint len, double* w_data)
|
|
|
|
|
{
|
|
|
|
|
double c = (2.0 / (len - 1.0)) - 1.0;
|
|
|
|
|
for (uint i = 0; i < (len >> 1); i++)
|
|
|
|
|
{
|
|
|
|
|
double w = 1.0 - ((c - i) * (c - i));
|
|
|
|
|
w_data[i] = data[i] * w;
|
|
|
|
|
w_data[len - 1 - i] = data[len - 1 - i] * w;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Calculates autocorrelation data from audio samples
|
|
|
|
|
* A Welch window function is applied before calculation.
|
|
|
|
|
*/
|
2009-08-20 04:09:53 +00:00
|
|
|
static public unsafe void
|
2009-08-17 03:39:53 +00:00
|
|
|
compute_autocorr(/*const*/ int* data, uint len, uint lag, double* autoc, double* window)
|
|
|
|
|
{
|
|
|
|
|
double* data1 = stackalloc double[(int)len + 16];
|
|
|
|
|
uint i, j;
|
|
|
|
|
double temp, temp2;
|
|
|
|
|
|
|
|
|
|
if (window == null)
|
|
|
|
|
apply_welch_window(data, len, data1);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
|
data1[i] = data[i] * window[i];
|
|
|
|
|
}
|
|
|
|
|
data1[len] = 0;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i <= lag; ++i)
|
|
|
|
|
{
|
|
|
|
|
temp = 1.0;
|
|
|
|
|
temp2 = 1.0;
|
|
|
|
|
for (j = 0; j <= lag - i; ++j)
|
|
|
|
|
temp += data1[j + i] * data1[j];
|
|
|
|
|
|
|
|
|
|
double* finish = data1 + len - i;
|
|
|
|
|
for (double* pdata = data1 + lag + 1 - i; pdata < finish; pdata += 2)
|
|
|
|
|
{
|
|
|
|
|
temp += pdata[i] * pdata[0];
|
|
|
|
|
temp2 += pdata[i + 1] * pdata[1];
|
|
|
|
|
}
|
|
|
|
|
autoc[i] = temp + temp2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//int sample, coeff;
|
|
|
|
|
//for (coeff = 0; coeff <= lag; coeff++)
|
|
|
|
|
// autoc[coeff] = 0.0;
|
|
|
|
|
//int data_len = (int)len;
|
|
|
|
|
//int limit = data_len - (int)lag - 1;
|
|
|
|
|
//for (sample = 0; sample <= limit; sample++)
|
|
|
|
|
//{
|
|
|
|
|
// double d = data1[sample];
|
|
|
|
|
// for (coeff = 0; coeff <= lag; coeff++)
|
|
|
|
|
// autoc[coeff] += d * data1[sample + coeff];
|
|
|
|
|
//}
|
|
|
|
|
//for (; sample < data_len; sample++)
|
|
|
|
|
//{
|
|
|
|
|
// double d = data1[sample];
|
|
|
|
|
// for (coeff = 0; coeff < data_len - sample; coeff++)
|
|
|
|
|
// autoc[coeff] += d * data1[sample + coeff];
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Levinson-Durbin recursion.
|
|
|
|
|
* Produces LPC coefficients from autocorrelation data.
|
|
|
|
|
*/
|
2009-08-20 04:09:53 +00:00
|
|
|
public static unsafe void
|
2009-08-17 03:39:53 +00:00
|
|
|
compute_lpc_coefs(/*const*/ double* autoc, uint max_order, double* reff,
|
|
|
|
|
double* lpc/*[][MAX_LPC_ORDER]*/)
|
|
|
|
|
{
|
|
|
|
|
double* lpc_tmp = stackalloc double[MAX_LPC_ORDER];
|
|
|
|
|
|
|
|
|
|
int i, j, i2;
|
|
|
|
|
double r, err, tmp;
|
|
|
|
|
|
|
|
|
|
if (max_order > MAX_LPC_ORDER)
|
|
|
|
|
throw new Exception("wierd");
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < max_order; i++)
|
|
|
|
|
lpc_tmp[i] = 0;
|
|
|
|
|
|
|
|
|
|
err = 1.0;
|
|
|
|
|
if (autoc != null)
|
|
|
|
|
err = autoc[0];
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < max_order; i++)
|
|
|
|
|
{
|
|
|
|
|
if (reff != null)
|
|
|
|
|
{
|
|
|
|
|
r = reff[i];
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
r = -autoc[i + 1];
|
|
|
|
|
for (j = 0; j < i; j++)
|
|
|
|
|
{
|
|
|
|
|
r -= lpc_tmp[j] * autoc[i - j];
|
|
|
|
|
}
|
|
|
|
|
r /= err;
|
|
|
|
|
err *= 1.0 - (r * r);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i2 = (i >> 1);
|
|
|
|
|
lpc_tmp[i] = r;
|
|
|
|
|
for (j = 0; j < i2; j++)
|
|
|
|
|
{
|
|
|
|
|
tmp = lpc_tmp[j];
|
|
|
|
|
lpc_tmp[j] += r * lpc_tmp[i - 1 - j];
|
|
|
|
|
lpc_tmp[i - 1 - j] += r * tmp;
|
|
|
|
|
}
|
|
|
|
|
if (0 != (i & 1))
|
|
|
|
|
{
|
|
|
|
|
lpc_tmp[j] += lpc_tmp[j] * r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (j = 0; j <= i; j++)
|
|
|
|
|
{
|
|
|
|
|
lpc[i * MAX_LPC_ORDER + j] = -lpc_tmp[j];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-20 04:09:53 +00:00
|
|
|
public static unsafe void
|
|
|
|
|
compute_schur_reflection(/*const*/ double* autoc, uint max_order,
|
|
|
|
|
double* reff/*[][MAX_LPC_ORDER]*/)
|
2009-08-17 03:39:53 +00:00
|
|
|
{
|
|
|
|
|
double* gen0 = stackalloc double[MAX_LPC_ORDER];
|
|
|
|
|
double* gen1 = stackalloc double[MAX_LPC_ORDER];
|
|
|
|
|
|
|
|
|
|
// Schur recursion
|
|
|
|
|
for (uint i = 0; i < max_order; i++)
|
|
|
|
|
gen0[i] = gen1[i] = autoc[i + 1];
|
|
|
|
|
|
|
|
|
|
double error = autoc[0];
|
|
|
|
|
reff[0] = -gen1[0] / error;
|
|
|
|
|
error += gen1[0] * reff[0];
|
|
|
|
|
for (uint i = 1; i < max_order; i++)
|
|
|
|
|
{
|
|
|
|
|
for (uint j = 0; j < max_order - i; j++)
|
|
|
|
|
{
|
|
|
|
|
gen1[j] = gen1[j + 1] + reff[i - 1] * gen0[j];
|
|
|
|
|
gen0[j] = gen1[j + 1] * reff[i - 1] + gen0[j];
|
|
|
|
|
}
|
|
|
|
|
reff[i] = -gen1[0] / error;
|
|
|
|
|
error += gen1[0] * reff[i];
|
|
|
|
|
}
|
2009-08-20 04:09:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Compute LPC coefs for Flake.OrderMethod._EST
|
|
|
|
|
* Faster LPC coeff computation by first calculating the reflection coefficients
|
|
|
|
|
* using Schur recursion. That allows for estimating the optimal order before
|
|
|
|
|
* running Levinson recursion.
|
|
|
|
|
*/
|
|
|
|
|
public static unsafe uint
|
|
|
|
|
compute_lpc_coefs_est(/*const*/ double* autoc, uint max_order,
|
|
|
|
|
double* lpc/*[][MAX_LPC_ORDER]*/)
|
|
|
|
|
{
|
|
|
|
|
double* reff = stackalloc double[MAX_LPC_ORDER];
|
|
|
|
|
|
|
|
|
|
// Schur recursion
|
|
|
|
|
compute_schur_reflection(autoc, max_order, reff);
|
2009-08-17 03:39:53 +00:00
|
|
|
|
|
|
|
|
// Estimate optimal order using reflection coefficients
|
|
|
|
|
uint order_est = 1;
|
|
|
|
|
for (int i = (int)max_order - 1; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
if (Math.Abs(reff[i]) > 0.10)
|
|
|
|
|
{
|
|
|
|
|
order_est = (uint)i + 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Levinson recursion
|
|
|
|
|
compute_lpc_coefs(null, order_est, reff, lpc);
|
|
|
|
|
return order_est;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Quantize LPC coefficients
|
|
|
|
|
*/
|
|
|
|
|
public static unsafe void
|
|
|
|
|
quantize_lpc_coefs(double* lpc_in, int order, uint precision, int* lpc_out,
|
|
|
|
|
out int shift)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
double d, cmax, error;
|
|
|
|
|
int qmax;
|
|
|
|
|
int sh, q;
|
|
|
|
|
|
|
|
|
|
// define maximum levels
|
|
|
|
|
qmax = (1 << ((int)precision - 1)) - 1;
|
|
|
|
|
|
|
|
|
|
// find maximum coefficient value
|
|
|
|
|
cmax = 0.0;
|
|
|
|
|
for (i = 0; i < order; i++)
|
|
|
|
|
{
|
|
|
|
|
d = Math.Abs(lpc_in[i]);
|
|
|
|
|
if (d > cmax)
|
|
|
|
|
cmax = d;
|
|
|
|
|
}
|
|
|
|
|
// if maximum value quantizes to zero, return all zeros
|
|
|
|
|
if (cmax * (1 << 15) < 1.0)
|
|
|
|
|
{
|
|
|
|
|
shift = 0;
|
|
|
|
|
for (i = 0; i < order; i++)
|
|
|
|
|
lpc_out[i] = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// calculate level shift which scales max coeff to available bits
|
|
|
|
|
sh = 15;
|
|
|
|
|
while ((cmax * (1 << sh) > qmax) && (sh > 0))
|
|
|
|
|
{
|
|
|
|
|
sh--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// since negative shift values are unsupported in decoder, scale down
|
|
|
|
|
// coefficients instead
|
|
|
|
|
if (sh == 0 && cmax > qmax)
|
|
|
|
|
{
|
|
|
|
|
double scale = ((double)qmax) / cmax;
|
|
|
|
|
for (i = 0; i < order; i++)
|
|
|
|
|
{
|
|
|
|
|
lpc_in[i] *= scale;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// output quantized coefficients and level shift
|
|
|
|
|
error = 0;
|
|
|
|
|
for (i = 0; i < order; i++)
|
|
|
|
|
{
|
|
|
|
|
error += lpc_in[i] * (1 << sh);
|
|
|
|
|
q = (int)(error + 0.5);
|
|
|
|
|
if (q <= -qmax) q = -qmax + 1;
|
|
|
|
|
if (q > qmax) q = qmax;
|
|
|
|
|
error -= q;
|
|
|
|
|
lpc_out[i] = q;
|
|
|
|
|
}
|
|
|
|
|
shift = sh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Calculate LPC coefficients for multiple orders
|
|
|
|
|
*/
|
|
|
|
|
public static unsafe uint
|
|
|
|
|
calc_coefs(/*const*/ int* samples, uint blocksize, uint max_order, OrderMethod omethod, double* lpcs, double* window)
|
|
|
|
|
{
|
|
|
|
|
double* autoc = stackalloc double[MAX_LPC_ORDER + 1];
|
|
|
|
|
|
|
|
|
|
compute_autocorr(samples, blocksize, max_order + 1, autoc, window);
|
|
|
|
|
|
|
|
|
|
uint opt_order = max_order;
|
|
|
|
|
if (omethod == OrderMethod.Estimate || omethod == OrderMethod.EstSearch)
|
|
|
|
|
opt_order = compute_lpc_coefs_est(autoc, max_order, lpcs);
|
|
|
|
|
else
|
|
|
|
|
compute_lpc_coefs(autoc, max_order, null, lpcs);
|
|
|
|
|
|
|
|
|
|
return opt_order;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static unsafe void
|
|
|
|
|
encode_residual(int* res, int* smp, int n, int order,
|
|
|
|
|
int* coefs, int shift)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < order; i++)
|
|
|
|
|
res[i] = smp[i];
|
|
|
|
|
|
|
|
|
|
int* s = smp;
|
|
|
|
|
int* r = res + order;
|
|
|
|
|
int c0 = coefs[0];
|
|
|
|
|
int c1 = coefs[1];
|
|
|
|
|
switch (order)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = c0 * *(s++);
|
|
|
|
|
*(r++) = *s - (pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*(r++) = *(s--) - (pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*(r++) = *s - (pred >> shift);
|
|
|
|
|
s -= 2;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*(r++) = *s - (pred >> shift);
|
|
|
|
|
s -= 3;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[4] * *(s++);
|
|
|
|
|
pred += coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*(r++) = *s - (pred >> shift);
|
|
|
|
|
s -= 4;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[5] * *(s++);
|
|
|
|
|
pred += coefs[4] * *(s++);
|
|
|
|
|
pred += coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*(r++) = *s - (pred >> shift);
|
|
|
|
|
s -= 5;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[6] * *(s++);
|
|
|
|
|
pred += coefs[5] * *(s++);
|
|
|
|
|
pred += coefs[4] * *(s++);
|
|
|
|
|
pred += coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*(r++) = *s - (pred >> shift);
|
|
|
|
|
s -= 6;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[7] * *(s++);
|
|
|
|
|
pred += coefs[6] * *(s++);
|
|
|
|
|
pred += coefs[5] * *(s++);
|
|
|
|
|
pred += coefs[4] * *(s++);
|
|
|
|
|
pred += coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*(r++) = *s - (pred >> shift);
|
|
|
|
|
s -= 7;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
for (int i = order; i < n; i++)
|
|
|
|
|
{
|
|
|
|
|
s = smp + i - order;
|
|
|
|
|
int pred = 0;
|
|
|
|
|
int* co = coefs + order - 1;
|
|
|
|
|
int* c7 = coefs + 7;
|
|
|
|
|
while (co > c7)
|
|
|
|
|
pred += *(co--) * *(s++);
|
|
|
|
|
pred += coefs[7] * *(s++);
|
|
|
|
|
pred += coefs[6] * *(s++);
|
|
|
|
|
pred += coefs[5] * *(s++);
|
|
|
|
|
pred += coefs[4] * *(s++);
|
|
|
|
|
pred += coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*(r++) = *s - (pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-20 04:09:53 +00:00
|
|
|
public static unsafe void
|
|
|
|
|
encode_residual_long(int* res, int* smp, int n, int order,
|
|
|
|
|
int* coefs, int shift)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < order; i++)
|
|
|
|
|
res[i] = smp[i];
|
|
|
|
|
|
|
|
|
|
int* s = smp;
|
|
|
|
|
int* r = res + order;
|
|
|
|
|
int c0 = coefs[0];
|
|
|
|
|
int c1 = coefs[1];
|
|
|
|
|
switch (order)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = c0 * (long)*(s++);
|
|
|
|
|
*(r++) = *s - (int)(pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*(r++) = *(s--) - (int)(pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*(r++) = *s - (int)(pred >> shift);
|
|
|
|
|
s -= 2;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*(r++) = *s - (int)(pred >> shift);
|
|
|
|
|
s -= 3;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[4] * (long)*(s++);
|
|
|
|
|
pred += coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*(r++) = *s - (int)(pred >> shift);
|
|
|
|
|
s -= 4;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[5] * (long)*(s++);
|
|
|
|
|
pred += coefs[4] * (long)*(s++);
|
|
|
|
|
pred += coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*(r++) = *s - (int)(pred >> shift);
|
|
|
|
|
s -= 5;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[6] * (long)*(s++);
|
|
|
|
|
pred += coefs[5] * (long)*(s++);
|
|
|
|
|
pred += coefs[4] * (long)*(s++);
|
|
|
|
|
pred += coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*(r++) = *s - (int)(pred >> shift);
|
|
|
|
|
s -= 6;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[7] * (long)*(s++);
|
|
|
|
|
pred += coefs[6] * (long)*(s++);
|
|
|
|
|
pred += coefs[5] * (long)*(s++);
|
|
|
|
|
pred += coefs[4] * (long)*(s++);
|
|
|
|
|
pred += coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*(r++) = *s - (int)(pred >> shift);
|
|
|
|
|
s -= 7;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
for (int i = order; i < n; i++)
|
|
|
|
|
{
|
|
|
|
|
s = smp + i - order;
|
|
|
|
|
long pred = 0;
|
|
|
|
|
int* co = coefs + order - 1;
|
|
|
|
|
int* c7 = coefs + 7;
|
|
|
|
|
while (co > c7)
|
|
|
|
|
pred += *(co--) * (long)*(s++);
|
|
|
|
|
pred += coefs[7] * (long)*(s++);
|
|
|
|
|
pred += coefs[6] * (long)*(s++);
|
|
|
|
|
pred += coefs[5] * (long)*(s++);
|
|
|
|
|
pred += coefs[4] * (long)*(s++);
|
|
|
|
|
pred += coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*(r++) = *s - (int)(pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-17 03:39:53 +00:00
|
|
|
public static unsafe void
|
|
|
|
|
decode_residual(int* res, int* smp, int n, int order,
|
|
|
|
|
int* coefs, int shift)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < order; i++)
|
|
|
|
|
smp[i] = res[i];
|
|
|
|
|
|
|
|
|
|
int* s = smp;
|
|
|
|
|
int* r = res + order;
|
|
|
|
|
int c0 = coefs[0];
|
|
|
|
|
int c1 = coefs[1];
|
|
|
|
|
switch (order)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = c0 * *(s++);
|
|
|
|
|
*s = *(r++) + (pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*(s--) = *(r++) + (pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*s = *(r++) + (pred >> shift);
|
|
|
|
|
s -= 2;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*s = *(r++) + (pred >> shift);
|
|
|
|
|
s -= 3;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[4] * *(s++);
|
|
|
|
|
pred += coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*s = *(r++) + (pred >> shift);
|
|
|
|
|
s -= 4;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[5] * *(s++);
|
|
|
|
|
pred += coefs[4] * *(s++);
|
|
|
|
|
pred += coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*s = *(r++) + (pred >> shift);
|
|
|
|
|
s -= 5;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[6] * *(s++);
|
|
|
|
|
pred += coefs[5] * *(s++);
|
|
|
|
|
pred += coefs[4] * *(s++);
|
|
|
|
|
pred += coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*s = *(r++) + (pred >> shift);
|
|
|
|
|
s -= 6;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
int pred = coefs[7] * *(s++);
|
|
|
|
|
pred += coefs[6] * *(s++);
|
|
|
|
|
pred += coefs[5] * *(s++);
|
|
|
|
|
pred += coefs[4] * *(s++);
|
|
|
|
|
pred += coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*s = *(r++) + (pred >> shift);
|
|
|
|
|
s -= 7;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
for (int i = order; i < n; i++)
|
|
|
|
|
{
|
|
|
|
|
s = smp + i - order;
|
|
|
|
|
int pred = 0;
|
|
|
|
|
int* co = coefs + order - 1;
|
|
|
|
|
int* c7 = coefs + 7;
|
|
|
|
|
while (co > c7)
|
|
|
|
|
pred += *(co--) * *(s++);
|
|
|
|
|
pred += coefs[7] * *(s++);
|
|
|
|
|
pred += coefs[6] * *(s++);
|
|
|
|
|
pred += coefs[5] * *(s++);
|
|
|
|
|
pred += coefs[4] * *(s++);
|
|
|
|
|
pred += coefs[3] * *(s++);
|
|
|
|
|
pred += coefs[2] * *(s++);
|
|
|
|
|
pred += c1 * *(s++);
|
|
|
|
|
pred += c0 * *(s++);
|
|
|
|
|
*s = *(r++) + (pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
public static unsafe void
|
|
|
|
|
decode_residual_long(int* res, int* smp, int n, int order,
|
|
|
|
|
int* coefs, int shift)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < order; i++)
|
|
|
|
|
smp[i] = res[i];
|
|
|
|
|
|
|
|
|
|
int* s = smp;
|
|
|
|
|
int* r = res + order;
|
|
|
|
|
int c0 = coefs[0];
|
|
|
|
|
int c1 = coefs[1];
|
|
|
|
|
switch (order)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = c0 * (long)*(s++);
|
|
|
|
|
*s = *(r++) + (int)(pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*(s--) = *(r++) + (int)(pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*s = *(r++) + (int)(pred >> shift);
|
|
|
|
|
s -= 2;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*s = *(r++) + (int)(pred >> shift);
|
|
|
|
|
s -= 3;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[4] * (long)*(s++);
|
|
|
|
|
pred += coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*s = *(r++) + (int)(pred >> shift);
|
|
|
|
|
s -= 4;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[5] * (long)*(s++);
|
|
|
|
|
pred += coefs[4] * (long)*(s++);
|
|
|
|
|
pred += coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*s = *(r++) + (int)(pred >> shift);
|
|
|
|
|
s -= 5;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 7:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[6] * (long)*(s++);
|
|
|
|
|
pred += coefs[5] * (long)*(s++);
|
|
|
|
|
pred += coefs[4] * (long)*(s++);
|
|
|
|
|
pred += coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*s = *(r++) + (int)(pred >> shift);
|
|
|
|
|
s -= 6;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
for (int i = n - order; i > 0; i--)
|
|
|
|
|
{
|
|
|
|
|
long pred = coefs[7] * (long)*(s++);
|
|
|
|
|
pred += coefs[6] * (long)*(s++);
|
|
|
|
|
pred += coefs[5] * (long)*(s++);
|
|
|
|
|
pred += coefs[4] * (long)*(s++);
|
|
|
|
|
pred += coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*s = *(r++) + (int)(pred >> shift);
|
|
|
|
|
s -= 7;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
for (int i = order; i < n; i++)
|
|
|
|
|
{
|
|
|
|
|
s = smp + i - order;
|
|
|
|
|
long pred = 0;
|
|
|
|
|
int* co = coefs + order - 1;
|
|
|
|
|
int* c7 = coefs + 7;
|
|
|
|
|
while (co > c7)
|
|
|
|
|
pred += *(co--) * (long)*(s++);
|
|
|
|
|
pred += coefs[7] * (long)*(s++);
|
|
|
|
|
pred += coefs[6] * (long)*(s++);
|
|
|
|
|
pred += coefs[5] * (long)*(s++);
|
|
|
|
|
pred += coefs[4] * (long)*(s++);
|
|
|
|
|
pred += coefs[3] * (long)*(s++);
|
|
|
|
|
pred += coefs[2] * (long)*(s++);
|
|
|
|
|
pred += c1 * (long)*(s++);
|
|
|
|
|
pred += c0 * (long)*(s++);
|
|
|
|
|
*s = *(r++) + (int)(pred >> shift);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|