package org.jcodec.audio; import java.lang.IllegalArgumentException; import java.nio.FloatBuffer; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * Lanczos resampler * * @author The JCodec project * */ public class LanczosInterpolator implements AudioFilter { public static double lanczos(double x, int a) { return x < -a ? 0 : x > a ? 0 : (a * Math.sin(Math.PI * x) * Math.sin(Math.PI * x / a)) / (Math.PI * Math.PI * x * x); } private double rateStep; public LanczosInterpolator(int fromRate, int toRate) { rateStep = (double) fromRate / toRate; } public void filter(FloatBuffer[] _in, long[] pos, FloatBuffer[] out) { if (_in.length != 1) throw new IllegalArgumentException(this.getClass().getName() + " filter is designed to work only on one input"); if (out.length != 1) throw new IllegalArgumentException(this.getClass().getName() + " filter is designed to work only on one output"); FloatBuffer in0 = _in[0]; FloatBuffer out0 = out[0]; if (out0.remaining() < (in0.remaining() - 6) / rateStep) throw new IllegalArgumentException("Output buffer is too small"); if (in0.remaining() <= 6) throw new IllegalArgumentException("Input buffer should contain > 6 samples."); for (int outSample = 0;; outSample++) { double inSample = 3 + outSample * rateStep + Math.ceil(pos[0] / rateStep) * rateStep - pos[0]; int p0i = (int) Math.floor(inSample); int q0i = (int) Math.ceil(inSample); if (p0i >= in0.limit() - 3) { in0.position(p0i - 3); break; } double p0d = p0i - inSample; if (p0d < -.001) { double q0d = q0i - inSample; double p0c = lanczos(p0d, 3); double q0c = lanczos(q0d, 3); double p1c = lanczos(p0d - 1, 3); double q1c = lanczos(q0d + 1, 3); double p2c = lanczos(p0d - 2, 3); double q2c = lanczos(q0d + 2, 3); double factor = 1d / (p0c + p1c + p2c + q0c + q1c + q2c); out0.put((float) ((in0.get(q0i) * q0c + in0.get(q0i + 1) * q1c + in0.get(q0i + 2) * q2c + in0.get(p0i) * p0c + in0.get(p0i - 1) * p1c + in0.get(p0i - 2) * p2c) * factor)); } else { out0.put(in0.get(p0i)); } } } @Override public int getDelay() { return 3; } @Override public int getNInputs() { return 1; } @Override public int getNOutputs() { return 1; } }