/* JOrbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk<ymnk@jcraft.com> * * Many thanks to * Monty <monty@xiph.org> and * The XIPHOPHORUS Company http://www.xiph.org/ . * JOrbis has been based on their awesome works, Vorbis codec. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * This program 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 Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package com.jcraft.jorbis; import com.jcraft.jogg.*; class Floor0 extends FuncFloor{ void pack(Object i, Buffer opb){ InfoFloor0 info=(InfoFloor0)i; opb.write(info.order,8); opb.write(info.rate,16); opb.write(info.barkmap,16); opb.write(info.ampbits,6); opb.write(info.ampdB,8); opb.write(info.numbooks-1,4); for(int j=0;j<info.numbooks;j++) opb.write(info.books[j],8); } Object unpack(Info vi , Buffer opb){ InfoFloor0 info=new InfoFloor0(); info.order=opb.read(8); info.rate=opb.read(16); info.barkmap=opb.read(16); info.ampbits=opb.read(6); info.ampdB=opb.read(8); info.numbooks=opb.read(4)+1; if((info.order<1)|| (info.rate<1)|| (info.barkmap<1)|| (info.numbooks<1)){ //free_info(info); return(null); } for(int j=0;j<info.numbooks;j++){ info.books[j]=opb.read(8); if(info.books[j]<0 || info.books[j]>=vi.books){ //free_info(info); return(null); } } return(info); // err_out: // free_info(info); // return(NULL); } Object look(DspState vd, InfoMode mi, Object i){ float scale; Info vi=vd.vi; InfoFloor0 info=(InfoFloor0)i; LookFloor0 look=new LookFloor0(); look.m=info.order; look.n=vi.blocksizes[mi.blockflag]/2; look.ln=info.barkmap; look.vi=info; look.lpclook.init(look.ln,look.m); // we choose a scaling constant so that: // floor(bark(rate/2-1)*C)=mapped-1 // floor(bark(rate/2)*C)=mapped scale=look.ln/toBARK((float)(info.rate/2.)); // the mapping from a linear scale to a smaller bark scale is // straightforward. We do *not* make sure that the linear mapping // does not skip bark-scale bins; the decoder simply skips them and // the encoder may do what it wishes in filling them. They're // necessary in some mapping combinations to keep the scale spacing // accurate look.linearmap=new int[look.n]; for(int j=0;j<look.n;j++){ int val=(int)Math.floor(toBARK((float)((info.rate/2.)/look.n*j)) *scale); // bark numbers represent band edges if(val>=look.ln)val=look.ln; // guard against the approximation look.linearmap[j]=val; } return look; } static float toBARK(float f){ return (float)(13.1*Math.atan(.00074*(f))+2.24*Math.atan((f)*(f)*1.85e-8)+1e-4*(f)); } Object state(Object i){ EchstateFloor0 state=new EchstateFloor0(); InfoFloor0 info=(InfoFloor0)i; // a safe size if usually too big (dim==1) state.codewords=new int[info.order]; state.curve=new float[info.barkmap]; state.frameno=-1; return(state); } void free_info(Object i){} void free_look(Object i){} void free_state(Object vs){} int forward(Block vb, Object i, float[] in, float[] out, Object vs){return 0;} float[] lsp=null; int inverse(Block vb, Object i, float[] out){ //System.err.println("Floor0.inverse "+i.getClass()+"]"); LookFloor0 look=(LookFloor0)i; InfoFloor0 info=look.vi; int ampraw=vb.opb.read(info.ampbits); if(ampraw>0){ // also handles the -1 out of data case int maxval=(1<<info.ampbits)-1; float amp=(float)ampraw/maxval*info.ampdB; int booknum=vb.opb.read(ilog(info.numbooks)); if(booknum!=-1 && booknum<info.numbooks){ synchronized(this){ if(lsp==null||lsp.length<look.m){ lsp=new float[look.m]; } else{ for(int j=0; j<look.m; j++)lsp[j]=0.f; } CodeBook b=vb.vd.fullbooks[info.books[booknum]]; float last=0.f; //memset(out,0,sizeof(float)*look->m); for(int j=0; j<look.m; j++)out[j]=0.0f; for(int j=0;j<look.m;j+=b.dim){ if(b.decodevs(lsp, j, vb.opb, 1, -1)==-1){ //goto eop; // memset(out,0,sizeof(float)*look->n); for(int k=0; k<look.n; k++)out[k]=0.0f; return(0); } } for(int j=0;j<look.m;){ for(int k=0;k<b.dim;k++,j++)lsp[j]+=last; last=lsp[j-1]; } // take the coefficients back to a spectral envelope curve /* lsp_to_lpc(out,out,look.m); lpc_to_curve(out,out,amp,look,"",0); for(int j=0;j<look.n;j++){ out[j]=fromdB(out[j]-info.ampdB); } */ Lsp.lsp_to_curve(out,look.linearmap,look.n,look.ln, lsp,look.m,amp,info.ampdB); return(1); } } } // eop: // memset(out,0,sizeof(float)*look->n); return(0); } Object inverse1(Block vb, Object i, Object memo){ //System.err.println("Floor0.inverse "+i.getClass()+"]"); LookFloor0 look=(LookFloor0)i; InfoFloor0 info=look.vi; float[] lsp=null; if(memo instanceof float[]){ lsp=(float[])memo; } int ampraw=vb.opb.read(info.ampbits); if(ampraw>0){ // also handles the -1 out of data case int maxval=(1<<info.ampbits)-1; float amp=(float)ampraw/maxval*info.ampdB; int booknum=vb.opb.read(ilog(info.numbooks)); if(booknum!=-1 && booknum<info.numbooks){ CodeBook b=vb.vd.fullbooks[info.books[booknum]]; float last=0.f; if(lsp==null||lsp.length<look.m+1){ lsp=new float[look.m+1]; } else{ for(int j=0; j<lsp.length; j++)lsp[j]=0.f; } for(int j=0;j<look.m;j+=b.dim){ if(b.decodev_set(lsp, j, vb.opb, b.dim)==-1){ //goto eop; return(null); } } for(int j=0;j<look.m;){ for(int k=0;k<b.dim;k++,j++)lsp[j]+=last; last=lsp[j-1]; } lsp[look.m]=amp; return(lsp); } } // eop: return(null); } int inverse2(Block vb, Object i, Object memo, float[] out){ //System.err.println("Floor0.inverse "+i.getClass()+"]"); LookFloor0 look=(LookFloor0)i; InfoFloor0 info=look.vi; if(memo!=null){ float[] lsp=(float[])memo; float amp=lsp[look.m]; Lsp.lsp_to_curve(out,look.linearmap,look.n,look.ln, lsp,look.m,amp,info.ampdB); return(1); } // eop: // memset(out,0,sizeof(float)*look->n); for(int j=0; j<look.n; j++){ out[j]=0.f; } return(0); } static float fromdB(float x){ return (float)(Math.exp((x)*.11512925)); } private static int ilog(int v){ int ret=0; while(v!=0){ ret++; v>>>=1; } return(ret); } static void lsp_to_lpc(float[] lsp, float[] lpc, int m){ int i,j,m2=m/2; float[] O=new float[m2]; float[] E=new float[m2]; float A; float[] Ae=new float[m2+1]; float[] Ao=new float[m2+1]; float B; float[] Be=new float[m2]; float[] Bo=new float[m2]; float temp; // even/odd roots setup for(i=0;i<m2;i++){ O[i]=(float)(-2.*Math.cos(lsp[i*2])); E[i]=(float)(-2.*Math.cos(lsp[i*2+1])); } // set up impulse response for(j=0;j<m2;j++){ Ae[j]=0.f; Ao[j]=1.f; Be[j]=0.f; Bo[j]=1.f; } Ao[j]=1.f; Ae[j]=1.f; // run impulse response for(i=1;i<m+1;i++){ A=B=0.f; for(j=0;j<m2;j++){ temp=O[j]*Ao[j]+Ae[j]; Ae[j]=Ao[j]; Ao[j]=A; A+=temp; temp=E[j]*Bo[j]+Be[j]; Be[j]=Bo[j]; Bo[j]=B; B+=temp; } lpc[i-1]=(A+Ao[j]+B-Ae[j])/2; Ao[j]=A; Ae[j]=B; } } static void lpc_to_curve(float[] curve, float[] lpc,float amp, LookFloor0 l, String name, int frameno){ // l->m+1 must be less than l->ln, but guard in case we get a bad stream float[] lcurve=new float[Math.max(l.ln*2,l.m*2+2)]; if(amp==0){ //memset(curve,0,sizeof(float)*l->n); for(int j=0; j<l.n; j++)curve[j]=0.0f; return; } l.lpclook.lpc_to_curve(lcurve,lpc,amp); for(int i=0;i<l.n;i++)curve[i]=lcurve[l.linearmap[i]]; } } class InfoFloor0{ int order; int rate; int barkmap; int ampbits; int ampdB; int numbooks; // <= 16 int[] books=new int[16]; } class LookFloor0{ int n; int ln; int m; int[] linearmap; InfoFloor0 vi; Lpc lpclook=new Lpc(); } class EchstateFloor0{ int[] codewords; float[] curve; long frameno; long codes; }