Linear Predictive Coding

ハードディスクを漁っていたらLinear Predictive Coding(線形予測符号)のJava実装が見つかったので公開してみる。

public class LinearPrediction {
	public double[] burg(double[] y, int P) {
		final int ly = y.length;
		final double[] f = Arrays.copyOf(y, y.length);
		final double[] b = Arrays.copyOf(y, y.length);
		final double[] k = new double[f.length];
		final double[] a = new double[P];

		for (int p = 0; p < P; ++p) {
			double f1 = 0;
			double f2 = 0;
			for (int n = p + 1; n < ly; ++n) {
				f1 += b[n - 1] * f[n];
				f2 += f[n] * f[n] + b[n - 1] * b[n - 1];
			}
			double k0 = -2.0 * f1 / f2;
			if (p + 1 == P && P == ly) {
				k0 = 0;
			}
			k[p] = k0;
			a[p] = k0;

			for (int i = 0; i < (p + 1) / 2; ++i) {
				final double ai = a[i];
				final double aj = a[p - i - 1];
				a[i] = ai + k0 * aj;
				a[p - i - 1] = aj + k0 * ai;
			}

			for (int n = p + 1; n < ly; ++n) {
				final double f0 = f[n] + k0 * b[n - 1];
				final double b0 = k0 * f[n] + b[n - 1];
				b[n - 1] = f1;
				f[n] = f0;
				f1 = b0;
			}
		}

		return a;
	}

	public void process(double[] x, int startIndex, int middleIndex, int endIndex) {
		final double[] a = burg(Arrays.copyOfRange(x, startIndex, middleIndex), middleIndex - startIndex);

		for (int n = middleIndex; n < endIndex; ++n) {
			double xx = 0;
			for (int i = 0; i < a.length; ++i) {
				xx -= a[i] * x[n - i - 1];
			}
			x[n] = xx;
		}
	}
}