/* RtLPCEngine.java (c) 2012-2014 Edward Swartz All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html */ package v9t9.engine.speech.encode; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; /** * @author ejs * */ public class RtLPCEngine implements ILPCEngine { private float[] corr; private float[] Zs; private Matrix R; private Matrix res; private int order; private LPCEncoderParams params; public RtLPCEngine(LPCEncoderParams params) { this.params = params; this.order = params.getOrder(); R = new Matrix( order, order ); res = new Matrix( order, order ); Zs = new float[order]; this.Zss = new float[order]; // allocate corr = new float[params.getFrameSize()]; } private float predict(float[] x, int offs, int len, LPCAnalysisFrame results) { int i,j; float power = 0.0f; float error, tmp; for( i = 0; i < order; i++ ) Zs[i] = x[order - i - 1 + offs]; // set the hope size int hope_size = len - order; // zero out the residue if( results.residue != null ) Arrays.fill(results.residue, 0); // find the MSE for( i = order; i < hope_size + order; i++ ) { tmp = 0.0f; for( j = 0; j < order; j++ ) tmp += Zs[j] * results.coefs[j]; for( j = order - 1; j > 0; j-- ) Zs[j] = Zs[j-1]; Zs[0] = x[i+offs]; error = x[i+offs] - tmp; power += error * error; if( results.residue != null ) results.residue[i] = error; } // power return (float)Math.sqrt(power) / hope_size; } @Override public float[] getY() { return corr; } //----------------------------------------------------------------------------- // name: lpc_analyze() // desc: ... //----------------------------------------------------------------------------- /* (non-Javadoc) * @see v9t9.audio.speech.encode.ILPCAnalysis#analyze(float[], int, int, v9t9.audio.speech.encode.LPCAnalysis.LPCAnalysisFrame) */ @Override public LPCAnalysisFrame analyze( float[] x, int offs, int len) { int i, j; LPCAnalysisFrame results = new LPCAnalysisFrame(order); results.coefsOffs = 1; if (this.corr == null || this.corr.length != len) { corr = new float[len]; } // find the autocorrelation of the signal, with pitch results.invPitch = autocorrelate( x, offs, len, corr ); results.pitch = results.invPitch != 0 ? (results.invPitch * params.getPlaybackHz() / params.getHertz() ) : 0; // construct the R matrix for( i = 0; i < order; i++ ) for( j = 0; j < order; j++ ) R.set(i, j, corr[Math.abs((int)(i-j))]); // invert R R.invert( res ); // find the coefficients A = P*R^(-1) results.coefs = new float[order + 1]; for( i = 0; i < order; i++ ) { results.coefs[i] = 0.0f; for( j = 0; j < order; j++ ) results.coefs[i] += R.at(i, j) * corr[1+j]; } // do the linear prediction to find residue results.power = predict( x, offs, len, results) ; results.powerScale = params.getFrameSize() ; return results; } static int numGraphs; static StringBuilder graphData = new StringBuilder(); static boolean showGraph = false; //----------------------------------------------------------------------------- // name: autocorrelate() // desc: ... //----------------------------------------------------------------------------- private float autocorrelate( float[] x, int offs, int len, float[] y ) { float norm, temp; int n, i, j, k; // refer to pp. 89 for variable name consistency for ( n = 0; n < len; n++ ) { temp = 0.0f; for ( i = 0; i < len - offs - n - 1; i++ ) temp += x[i + offs] * x[i+offs+n]; y[n] = temp; if (showGraph) { graphData.append(n + " " + y[n] + "\n"); } } if (showGraph) { graphData.append("\n"); numGraphs++; if (numGraphs == 63) { try { File tmp = File.createTempFile("grf", ".txt"); OutputStream os = new FileOutputStream(tmp); os.write(graphData.toString().getBytes()); os.close(); Runtime.getRuntime().exec("xgraph " + tmp); tmp.deleteOnExit(); } catch (IOException e) { e.printStackTrace(); } graphData.setLength(0); numGraphs = 0; } } // set temp to the first element of y temp = y[0]; // why? j = (int)(len * 0.02); // loop to the point y stops descreasing while( y[j] < temp && j < len ) { temp = y[j]; j++; } // yes temp = 0.0f; // find the max between j and the end for( i = j; i < len/2; i++ ) { if( y[i] > temp) { j = i; temp = y[i]; } } // detect voiced vs. unvoiced -- 0 means unvoiced norm = 1.0f / len; k = len; for( i = 0; i < len; i++ ) y[i] *= (k-i) * norm; if( (y[j] / y[0]) < 0.4 ) j = 0; if( j > len / 2 ) j = 0; // we return the pitch information return (float) j; } private int ticker; private boolean alt; private float[] Zss; //----------------------------------------------------------------------------- // name: lpc_synthesize() // desc: ... //----------------------------------------------------------------------------- public void synthesize( float[] y, int offs, int len, int playbackHz, LPCAnalysisFrame frame) { float output; int i, j; float invPitch = frame.invPitch * playbackHz / params.getHertz(); for( i = 0; i < len; i++ ) { output = 0.0f; if( invPitch == 0 ) { output = (float) (frame.power * 20 * ( 2.0f * Math.random() - 1.0f )); ticker = 0; if( i == (len - 1) || i == 0 ) Arrays.fill(Zss, 0); } else { ticker--; if( ticker <= 0 ) { ticker = (int)(invPitch + .5f); if( !alt ) { output = frame.power * invPitch * 1.0f; //output = frame.power; } } if( alt ) { j = (int)(invPitch+.5) - ticker + 0; if( j >= 0 && (j*4) < glot_pop_data.length ) { output = frame.power * invPitch * 0.5f * glot_pop_data[j*4] / (float)32767; //output = frame.power * glot_pop_data[j*4] / (float)32767; } else output *= .9f; } } for( j = 0; j < frame.coefs.length; j++ ) output += Zss[j] * frame.coefs[j]; for( j = frame.coefs.length - 1; j > 0; j-- ) Zss[j] = Zss[j-1]; Zss[0] = output; y[i + offs] = output; } } // data for glot_pop.raw... static float glot_pop_data[] = { 0.0f,0.0f,1.0f,-1.0f,0.0f,0.0f,0.0f,0.0f, 1.0f,1.0f,513.0f,561.0f,565.0f,499.0f,374.0f,188.0f, -42.0f,-306.0f,-571.0f,-821.0f,-1037.0f,-1214.0f,-1338.0f,-1422.0f, -1479.0f,-1520.0f,-1568.0f,-1628.0f,-1708.0f,-1814.0f,-1931.0f,-2062.0f, -2185.0f,-2293.0f,-2375.0f,-2432.0f,-2464.0f,-2476.0f,-2471.0f,-2458.0f, -2431.0f,-2397.0f,-2338.0f,-2247.0f,-2110.0f,-1916.0f,-1655.0f,-1330.0f, -950.0f,-528.0f,-91.0f,337.0f,730.0f,1059.0f,1310.0f,1467.0f, 1531.0f,1509.0f,1411.0f,1256.0f,1066.0f,847.0f,629.0f,415.0f, 217.0f,37.0f,-131.0f,-278.0f,-411.0f,-524.0f,-624.0f,-711.0f, -778.0f,-827.0f,-859.0f,-867.0f,-866.0f,-846.0f,-824.0f,-804.0f, -788.0f,-789.0f,-808.0f,-855.0f,-926.0f,-1019.0f,-1142.0f,-1282.0f, -1441.0f,-1617.0f,-1803.0f,-2007.0f,-2223.0f,-2446.0f,-2670.0f,-2886.0f, -3077.0f,-3235.0f,-3330.0f,-3347.0f,-3278.0f,-3107.0f,-2844.0f,-2499.0f, -2102.0f,-1674.0f,-1253.0f,-869.0f,-548.0f,-299.0f,-131.0f,-29.0f, 24.0f,59.0f,94.0f,150.0f,240.0f,368.0f,519.0f,688.0f, 856.0f,994.0f,1093.0f,1144.0f,1135.0f,1077.0f,968.0f,823.0f, 646.0f,458.0f,268.0f,82.0f,-93.0f,-255.0f,-395.0f,-523.0f, -641.0f,-749.0f,-858.0f,-979.0f,-1114.0f,-1266.0f,-1437.0f,-1610.0f, -1779.0f,-1925.0f,-2028.0f,-2073.0f,-2047.0f,-1953.0f,-1795.0f,-1592.0f, -1374.0f,-1167.0f,-995.0f,-888.0f,-851.0f,-891.0f,-983.0f,-1112.0f, -1239.0f,-1325.0f,-1345.0f,-1266.0f,-1081.0f,-788.0f,-412.0f,21.0f, 465.0f,881.0f,1223.0f,1460.0f,1576.0f,1556.0f,1423.0f,1201.0f, 934.0f,660.0f,430.0f,280.0f,234.0f,300.0f,459.0f,685.0f, 930.0f,1143.0f,1275.0f,1285.0f,1145.0f,866.0f,465.0f,-8.0f, -490.0f,-913.0f,-1208.0f,-1322.0f,-1233.0f,-941.0f,-472.0f,96.0f, 701.0f,1240.0f,1641.0f,1848.0f,1830.0f,1590.0f,1181.0f,678.0f, 174.0f,-238.0f,-481.0f,-502.0f,-293.0f,120.0f,687.0f,1322.0f, 1943.0f,2470.0f,2853.0f,3075.0f,3151.0f,3120.0f,3036.0f,2957.0f, 2929.0f,2977.0f,3082.0f,3206.0f,3299.0f,3295.0f,3153.0f,2863.0f, 2431.0f,1916.0f,1405.0f,999.0f,799.0f,891.0f,1299.0f,2024.0f, 2997.0f,4118.0f,5278.0f,6312.0f,7105.0f,7554.0f,7625.0f,7328.0f, 6724.0f,5925.0f,5063.0f,4280.0f,3700.0f,3391.0f,3411.0f,3737.0f, 4307.0f,5027.0f,5773.0f,6436.0f,6918.0f,7164.0f,7178.0f,7003.0f, 6733.0f,6509.0f,6468.0f,6734.0f,7386.0f,8444.0f,9841.0f,11430.0f, 12991.0f,14273.0f,15014.0f,14983.0f,14047.0f,12167.0f,9434.0f,6071.0f, 2379.0f,-1263.0f,-4504.0f,-7035.0f,-8657.0f,-9297.0f,-9036.0f,-8060.0f, -6653.0f,-5126.0f,-3761.0f,-2782.0f,-2285.0f,-2276.0f,-2655.0f,-3251.0f, -3867.0f,-4324.0f,-4512.0f,-4379.0f,-3970.0f,-3372.0f,-2719.0f,-2129.0f, -1704.0f,-1489.0f,-1470.0f,-1589.0f,-1747.0f,-1853.0f,-1844.0f,-1693.0f, -1423.0f,-1108.0f,-819.0f,-663.0f,-707.0f,-966.0f,-1411.0f,-1953.0f, -2478.0f,-2836.0f,-2913.0f,-2625.0f,-1947.0f,-922.0f,362.0f,1760.0f, 3116.0f,4278.0f,5127.0f,5586.0f,5646.0f,5340.0f,4750.0f,3974.0f, 3115.0f,2269.0f,1495.0f,822.0f,254.0f,-237.0f,-678.0f,-1090.0f, -1487.0f,-1856.0f,-2172.0f,-2406.0f,-2515.0f,-2473.0f,-2289.0f,-1978.0f, -1593.0f,-1201.0f,-876.0f,-681.0f,-661.0f,-836.0f,-1184.0f,-1664.0f, -2198.0f,-2717.0f,-3148.0f,-3432.0f,-3544.0f,-3495.0f,-3322.0f,-3073.0f, -2829.0f,-2648.0f,-2581.0f,-2666.0f,-2885.0f,-3213.0f,-3593.0f,-3957.0f, -4233.0f,-4365.0f,-4312.0f,-4064.0f,-3636.0f,-3057.0f,-2378.0f,-1656.0f, -945.0f,-289.0f,262.0f,697.0f,1002.0f,1167.0f,1205.0f,1115.0f, 917.0f,630.0f,272.0f,-130.0f,-548.0f,-946.0f,-1294.0f,-1572.0f, -1753.0f,-1837.0f,-1835.0f,-1763.0f,-1642.0f,-1510.0f,-1391.0f,-1303.0f, -1259.0f,-1251.0f,-1264.0f,-1281.0f,-1271.0f,-1229.0f,-1139.0f,-1000.0f, -835.0f,-669.0f,-530.0f,-446.0f,-440.0f,-517.0f,-678.0f,-905.0f, -1181.0f,-1471.0f,-1750.0f,-1999.0f,-2197.0f,-2333.0f,-2411.0f,-2422.0f, -2375.0f,-2259.0f,-2090.0f,-1850.0f,-1543.0f,-1169.0f,-737.0f,-260.0f, 232.0f,707.0f,1122.0f,1444.0f,1639.0f,1688.0f,1586.0f,1347.0f, 1010.0f,615.0f,212.0f,-153.0f,-440.0f,-635.0f,-733.0f,-759.0f, -745.0f,-744.0f,-793.0f,-930.0f,-1170.0f,-1513.0f,-1938.0f,-2401.0f, -2860.0f,-3257.0f,-3553.0f,-3720.0f,-3747.0f,-3643.0f,-3430.0f,-3141.0f, -2811.0f,-2480.0f,-2170.0f,-1903.0f,-1676.0f,-1497.0f,-1356.0f,-1241.0f, -1151.0f,-1083.0f,-1041.0f,-1016.0f,-1017.0f,-1041.0f,-1081.0f,-1127.0f, -1165.0f,-1182.0f,-1164.0f,-1110.0f,-1007.0f,-871.0f,-706.0f,-533.0f, -361.0f,-211.0f,-89.0f,-4.0f,51.0f,68.0f,63.0f,48.0f, 24.0f,5.0f,-12.0f,-22.0f,-26.0f,-23.0f,-17.0f,-10.0f, -5.0f,2.0f,4.0f,6.0f,6.0f,6.0f,5.0f,0.0f, 0.0f, 0 }; }