001/* JOrbis 002 * Copyright (C) 2000 ymnk, JCraft,Inc. 003 * 004 * Written by: 2000 ymnk<ymnk@jcaft.com> 005 * 006 * Many thanks to 007 * Monty <monty@xiph.org> and 008 * The XIPHOPHORUS Company http://www.xiph.org/ . 009 * JOrbis has been based on their awesome works, Vorbis codec. 010 * 011 * This program is free software; you can redistribute it and/or 012 * modify it under the terms of the GNU Library General Public License 013 * as published by the Free Software Foundation; either version 2 of 014 * the License, or (at your option) any later version. 015 016 * This program is distributed in the hope that it will be useful, 017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 019 * GNU Library General Public License for more details. 020 * 021 * You should have received a copy of the GNU Library General Public 022 * License along with this program; if not, write to the Free Software 023 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 024 */ 025 026package com.jcraft.jorbis; 027 028import com.jcraft.jogg.*; 029 030class Floor0 extends FuncFloor{ 031 032 void pack(Object i, Buffer opb){ 033 InfoFloor0 info=(InfoFloor0)i; 034 opb.write(info.order,8); 035 opb.write(info.rate,16); 036 opb.write(info.barkmap,16); 037 opb.write(info.ampbits,6); 038 opb.write(info.ampdB,8); 039 opb.write(info.numbooks-1,4); 040 for(int j=0;j<info.numbooks;j++) 041 opb.write(info.books[j],8); 042 } 043 044 Object unpack(Info vi , Buffer opb){ 045 InfoFloor0 info=new InfoFloor0(); 046 info.order=opb.read(8); 047 info.rate=opb.read(16); 048 info.barkmap=opb.read(16); 049 info.ampbits=opb.read(6); 050 info.ampdB=opb.read(8); 051 info.numbooks=opb.read(4)+1; 052 053 if((info.order<1)|| 054 (info.rate<1)|| 055 (info.barkmap<1)|| 056 (info.numbooks<1)){ 057 //free_info(info); 058 return(null); 059 } 060 061 for(int j=0;j<info.numbooks;j++){ 062 info.books[j]=opb.read(8); 063 if(info.books[j]<0 || info.books[j]>=vi.books){ 064 //free_info(info); 065 return(null); 066 } 067 } 068 return(info); 069// err_out: 070// free_info(info); 071// return(NULL); 072 } 073 Object look(DspState vd, InfoMode mi, Object i){ 074 float scale; 075 Info vi=vd.vi; 076 InfoFloor0 info=(InfoFloor0)i; 077 LookFloor0 look=new LookFloor0(); 078 look.m=info.order; 079 look.n=vi.blocksizes[mi.blockflag]/2; 080 look.ln=info.barkmap; 081 look.vi=info; 082 look.lpclook.init(look.ln,look.m); 083 084 // we choose a scaling constant so that: 085 // floor(bark(rate/2-1)*C)=mapped-1 086 // floor(bark(rate/2)*C)=mapped 087 scale=look.ln/toBARK((float)(info.rate/2.)); 088 089 // the mapping from a linear scale to a smaller bark scale is 090 // straightforward. We do *not* make sure that the linear mapping 091 // does not skip bark-scale bins; the decoder simply skips them and 092 // the encoder may do what it wishes in filling them. They're 093 // necessary in some mapping combinations to keep the scale spacing 094 // accurate 095 look.linearmap=new int[look.n]; 096 for(int j=0;j<look.n;j++){ 097 int val=(int)Math.floor(toBARK((float)((info.rate/2.)/look.n*j)) 098 *scale); // bark numbers represent band edges 099 if(val>=look.ln)val=look.ln; // guard against the approximation 100 look.linearmap[j]=val; 101 } 102 return look; 103 } 104 105 static float toBARK(float f){ 106 return (float)(13.1*Math.atan(.00074*(f))+2.24*Math.atan((f)*(f)*1.85e-8)+1e-4*(f)); 107 } 108 109 Object state(Object i){ 110 EchstateFloor0 state=new EchstateFloor0(); 111 InfoFloor0 info=(InfoFloor0)i; 112 113 // a safe size if usually too big (dim==1) 114 state.codewords=new int[info.order]; 115 state.curve=new float[info.barkmap]; 116 state.frameno=-1; 117 return(state); 118 } 119 void free_info(Object i){} 120 void free_look(Object i){} 121 void free_state(Object vs){} 122 int forward(Block vb, Object i, float[] in, float[] out, Object vs){return 0;} 123 124 float[] lsp=null; 125 int inverse(Block vb, Object i, float[] out){ 126 //System.err.println("Floor0.inverse "+i.getClass()+"]"); 127 LookFloor0 look=(LookFloor0)i; 128 InfoFloor0 info=look.vi; 129 int ampraw=vb.opb.read(info.ampbits); 130 if(ampraw>0){ // also handles the -1 out of data case 131 int maxval=(1<<info.ampbits)-1; 132 float amp=(float)ampraw/maxval*info.ampdB; 133 int booknum=vb.opb.read(ilog(info.numbooks)); 134 135 if(booknum!=-1 && booknum<info.numbooks){ 136 137 synchronized(this){ 138 if(lsp==null||lsp.length<look.m){ 139 lsp=new float[look.m]; 140 } 141 else{ 142 for(int j=0; j<look.m; j++)lsp[j]=0.f; 143 } 144 145 CodeBook b=vb.vd.fullbooks[info.books[booknum]]; 146 float last=0.f; 147 148 //memset(out,0,sizeof(float)*look->m); 149 for(int j=0; j<look.m; j++)out[j]=0.0f; 150 151 for(int j=0;j<look.m;j+=b.dim){ 152 if(b.decodevs(lsp, j, vb.opb, 1, -1)==-1){ 153 //goto eop; 154 // memset(out,0,sizeof(float)*look->n); 155 for(int k=0; k<look.n; k++)out[k]=0.0f; 156 return(0); 157 } 158 } 159 for(int j=0;j<look.m;){ 160 for(int k=0;k<b.dim;k++,j++)lsp[j]+=last; 161 last=lsp[j-1]; 162 } 163 // take the coefficients back to a spectral envelope curve 164 /* 165 lsp_to_lpc(out,out,look.m); 166 lpc_to_curve(out,out,amp,look,"",0); 167 for(int j=0;j<look.n;j++){ 168 out[j]=fromdB(out[j]-info.ampdB); 169 } 170 */ 171 Lsp.lsp_to_curve(out,look.linearmap,look.n,look.ln, 172 lsp,look.m,amp,info.ampdB); 173 174 return(1); 175 } 176 } 177 } 178// eop: 179// memset(out,0,sizeof(float)*look->n); 180 return(0); 181 } 182 183 Object inverse1(Block vb, Object i, Object memo){ 184 //System.err.println("Floor0.inverse "+i.getClass()+"]"); 185 LookFloor0 look=(LookFloor0)i; 186 InfoFloor0 info=look.vi; 187 float[] lsp=null; 188 if(memo instanceof float[]){ 189 lsp=(float[])memo; 190 } 191 192 int ampraw=vb.opb.read(info.ampbits); 193 if(ampraw>0){ // also handles the -1 out of data case 194 int maxval=(1<<info.ampbits)-1; 195 float amp=(float)ampraw/maxval*info.ampdB; 196 int booknum=vb.opb.read(ilog(info.numbooks)); 197 198 if(booknum!=-1 && booknum<info.numbooks){ 199 CodeBook b=vb.vd.fullbooks[info.books[booknum]]; 200 float last=0.f; 201 202 if(lsp==null||lsp.length<look.m+1){ 203 lsp=new float[look.m+1]; 204 } 205 else{ 206 for(int j=0; j<lsp.length; j++)lsp[j]=0.f; 207 } 208 209 for(int j=0;j<look.m;j+=b.dim){ 210 if(b.decodev_set(lsp, j, vb.opb, b.dim)==-1){ 211 //goto eop; 212 return(null); 213 } 214 } 215 216 for(int j=0;j<look.m;){ 217 for(int k=0;k<b.dim;k++,j++)lsp[j]+=last; 218 last=lsp[j-1]; 219 } 220 lsp[look.m]=amp; 221 return(lsp); 222 } 223 } 224// eop: 225 return(null); 226 } 227 228 int inverse2(Block vb, Object i, Object memo, float[] out){ 229 //System.err.println("Floor0.inverse "+i.getClass()+"]"); 230 LookFloor0 look=(LookFloor0)i; 231 InfoFloor0 info=look.vi; 232 233 if(memo!=null){ 234 float[] lsp=(float[])memo; 235 float amp=lsp[look.m]; 236 237 Lsp.lsp_to_curve(out,look.linearmap,look.n,look.ln, 238 lsp,look.m,amp,info.ampdB); 239 return(1); 240 } 241// eop: 242// memset(out,0,sizeof(float)*look->n); 243 for(int j=0; j<look.n; j++){ 244 out[j]=0.f; 245 } 246 return(0); 247 } 248 249 static float fromdB(float x){ 250 return (float)(Math.exp((x)*.11512925)); 251 } 252 private static int ilog(int v){ 253 int ret=0; 254 while(v!=0){ 255 ret++; 256 v>>>=1; 257 } 258 return(ret); 259 } 260 261 static void lsp_to_lpc(float[] lsp, float[] lpc, int m){ 262 int i,j,m2=m/2; 263 float[] O=new float[m2]; 264 float[] E=new float[m2]; 265 float A; 266 float[] Ae=new float[m2+1]; 267 float[] Ao=new float[m2+1]; 268 float B; 269 float[] Be=new float[m2]; 270 float[] Bo=new float[m2]; 271 float temp; 272 273 // even/odd roots setup 274 for(i=0;i<m2;i++){ 275 O[i]=(float)(-2.*Math.cos(lsp[i*2])); 276 E[i]=(float)(-2.*Math.cos(lsp[i*2+1])); 277 } 278 279 // set up impulse response 280 for(j=0;j<m2;j++){ 281 Ae[j]=0.f; 282 Ao[j]=1.f; 283 Be[j]=0.f; 284 Bo[j]=1.f; 285 } 286 Ao[j]=1.f; 287 Ae[j]=1.f; 288 289 // run impulse response 290 for(i=1;i<m+1;i++){ 291 A=B=0.f; 292 for(j=0;j<m2;j++){ 293 temp=O[j]*Ao[j]+Ae[j]; 294 Ae[j]=Ao[j]; 295 Ao[j]=A; 296 A+=temp; 297 298 temp=E[j]*Bo[j]+Be[j]; 299 Be[j]=Bo[j]; 300 Bo[j]=B; 301 B+=temp; 302 } 303 lpc[i-1]=(A+Ao[j]+B-Ae[j])/2; 304 Ao[j]=A; 305 Ae[j]=B; 306 } 307 } 308 309 static void lpc_to_curve(float[] curve, float[] lpc,float amp, 310 LookFloor0 l, String name, int frameno){ 311 // l->m+1 must be less than l->ln, but guard in case we get a bad stream 312 float[] lcurve=new float[Math.max(l.ln*2,l.m*2+2)]; 313 314 if(amp==0){ 315 //memset(curve,0,sizeof(float)*l->n); 316 for(int j=0; j<l.n; j++)curve[j]=0.0f; 317 return; 318 } 319 l.lpclook.lpc_to_curve(lcurve,lpc,amp); 320 321 for(int i=0;i<l.n;i++)curve[i]=lcurve[l.linearmap[i]]; 322 } 323} 324 325class InfoFloor0{ 326 int order; 327 int rate; 328 int barkmap; 329 330 int ampbits; 331 int ampdB; 332 333 int numbooks; // <= 16 334 int[] books=new int[16]; 335} 336 337class LookFloor0{ 338 int n; 339 int ln; 340 int m; 341 int[] linearmap; 342 343 InfoFloor0 vi; 344 Lpc lpclook=new Lpc(); 345} 346 347class EchstateFloor0{ 348 int[] codewords; 349 float[] curve; 350 long frameno; 351 long codes; 352}