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 Mapping0 extends FuncMapping{ 031 static int seq=0; 032 void free_info(Object imap){}; 033 void free_look(Object imap){ 034/* 035 LookMapping0 l=(LookMapping0)imap; 036 InfoMapping0 info=l.map; 037 if(l!=null){ 038 for(int i=0;i<l.map.submaps;i++){ 039 l.time_func[i].free_look(l.time_look[i]); 040 l.floor_func[i].free_look(l.floor_look[i]); 041 l.residue_func[i].free_look(l.residue_look[i]); 042 if(l.psy_look!=null)l.psy_look[i].clear(); 043 } 044 } 045 046 if(l.floor_state!=null){ 047 for(int i=0;i<l.ch;i++) 048 l.floor_func[info.chmuxlist[i]].free_state(l.floor_state[i]); 049 //free(l.floor_state); 050 } 051 052 if(l.decay!=null){ 053 for(int i=0;i<l.ch;i++){ 054 //if(l.decay[i])free(l->decay[i]); 055 l.decay[i]=null; 056 } 057 //free(l->decay); 058 l.decay=null; 059 } 060 //free(l->time_func); 061 //free(l->floor_func); 062 //free(l->residue_func); 063 //free(l->time_look); 064 //free(l->floor_look); 065 //free(l->residue_look); 066 //f(l->psy_look)free(l->psy_look); 067 l.time_func=null; 068 l.floor_func=null; 069 l.residue_func=null; 070 l.time_look=null; 071 l.floor_look=null; 072 l.residue_look=null; 073 //memset(l,0,sizeof(vorbis_look_mapping0)); 074 //free(l); 075*/ 076 } 077 078 Object look(DspState vd, InfoMode vm, Object m){ 079//System.err.println("Mapping0.look"); 080 Info vi=vd.vi; 081 LookMapping0 look=new LookMapping0(); 082 InfoMapping0 info=look.map=(InfoMapping0)m; 083 look.mode=vm; 084 085 look.time_look=new Object[info.submaps]; 086 look.floor_look=new Object[info.submaps]; 087 look.residue_look=new Object[info.submaps]; 088 089/* 090 if(vd.analysisp!=0){ 091 look.floor_state=new Object[vi.channels]; 092 } 093 if(vi.psys!=0){ 094 look.psy_look=new PsyLook[info.submaps]; 095 for(int i=0; i<info.submaps; i++){ look.psy_look[i]=new PsyLook(); } 096 } 097*/ 098 099 look.time_func=new FuncTime[info.submaps]; 100 look.floor_func=new FuncFloor[info.submaps]; 101 look.residue_func=new FuncResidue[info.submaps]; 102 103 for(int i=0;i<info.submaps;i++){ 104 int timenum=info.timesubmap[i]; 105 int floornum=info.floorsubmap[i]; 106 int resnum=info.residuesubmap[i]; 107 108 look.time_func[i]=FuncTime.time_P[vi.time_type[timenum]]; 109 look.time_look[i]=look.time_func[i].look(vd,vm,vi.time_param[timenum]); 110 look.floor_func[i]=FuncFloor.floor_P[vi.floor_type[floornum]]; 111 look.floor_look[i]=look.floor_func[i]. 112 look(vd,vm,vi.floor_param[floornum]); 113 look.residue_func[i]=FuncResidue.residue_P[vi.residue_type[resnum]]; 114 look.residue_look[i]=look.residue_func[i]. 115 look(vd,vm,vi.residue_param[resnum]); 116 117/* 118 if(vi.psys!=0 && vd.analysisp!=0){ 119 int psynum=info.psysubmap[i]; 120 look.psy_look[i].init(vi.psy_param[psynum], 121 vi.blocksizes[vm.blockflag]/2,vi.rate); 122 } 123*/ 124 } 125 126 if(vi.psys!=0 && vd.analysisp!=0){ 127 /* 128 if(info->psy[0] != info->psy[1]){ 129 130 int psynum=info->psy[0]; 131 look->psy_look[0]=_ogg_calloc(1,sizeof(vorbis_look_psy)); 132 _vp_psy_init(look->psy_look[0],ci->psy_param[psynum], 133 ci->psy_g_param, 134 ci->blocksizes[vm->blockflag]/2,vi->rate); 135 136 psynum=info->psy[1]; 137 look->psy_look[1]=_ogg_calloc(1,sizeof(vorbis_look_psy)); 138 _vp_psy_init(look->psy_look[1],ci->psy_param[psynum], 139 ci->psy_g_param, 140 ci->blocksizes[vm->blockflag]/2,vi->rate); 141 }else{ 142 143 int psynum=info->psy[0]; 144 look->psy_look[0]=_ogg_calloc(1,sizeof(vorbis_look_psy)); 145 look->psy_look[1]=look->psy_look[0]; 146 _vp_psy_init(look->psy_look[0],ci->psy_param[psynum], 147 ci->psy_g_param, 148 ci->blocksizes[vm->blockflag]/2,vi->rate); 149 150 } 151 */ 152 } 153 154 look.ch=vi.channels; 155// if(vd->analysisp)drft_init(&look->fft_look,ci->blocksizes[vm->blockflag]); 156 157 return(look); 158//return null; 159 } 160 161 void pack(Info vi, Object imap, Buffer opb){ 162 InfoMapping0 info=(InfoMapping0)imap; 163 164 /* another 'we meant to do it this way' hack... up to beta 4, we 165 packed 4 binary zeros here to signify one submapping in use. We 166 now redefine that to mean four bitflags that indicate use of 167 deeper features; bit0:submappings, bit1:coupling, 168 bit2,3:reserved. This is backward compatable with all actual uses 169 of the beta code. */ 170 171 if(info.submaps>1){ 172 opb.write(1,1); 173 opb.write(info.submaps-1,4); 174 } 175 else{ 176 opb.write(0,1); 177 } 178 179 if(info.coupling_steps>0){ 180 opb.write(1,1); 181 opb.write(info.coupling_steps-1,8); 182 for(int i=0;i<info.coupling_steps;i++){ 183 opb.write(info.coupling_mag[i],ilog2(vi.channels)); 184 opb.write(info.coupling_ang[i],ilog2(vi.channels)); 185 } 186 } 187 else{ 188 opb.write(0,1); 189 } 190 191 opb.write(0,2); /* 2,3:reserved */ 192 193 /* we don't write the channel submappings if we only have one... */ 194 if(info.submaps>1){ 195 for(int i=0;i<vi.channels;i++) 196 opb.write(info.chmuxlist[i],4); 197 } 198 for(int i=0;i<info.submaps;i++){ 199 opb.write(info.timesubmap[i],8); 200 opb.write(info.floorsubmap[i],8); 201 opb.write(info.residuesubmap[i],8); 202 } 203 } 204 205 // also responsible for range checking 206 Object unpack(Info vi, Buffer opb){ 207 InfoMapping0 info=new InfoMapping0(); 208 209 // !!!! 210 if(opb.read(1)!=0){ 211 info.submaps=opb.read(4)+1; 212 } 213 else{ 214 info.submaps=1; 215 } 216 217 if(opb.read(1)!=0){ 218 info.coupling_steps=opb.read(8)+1; 219 220 for(int i=0;i<info.coupling_steps;i++){ 221 int testM=info.coupling_mag[i]=opb.read(ilog2(vi.channels)); 222 int testA=info.coupling_ang[i]=opb.read(ilog2(vi.channels)); 223 224 if(testM<0 || 225 testA<0 || 226 testM==testA || 227 testM>=vi.channels || 228 testA>=vi.channels){ 229 //goto err_out; 230 info.free(); 231 return(null); 232 } 233 } 234 } 235 236 if(opb.read(2)>0){ /* 2,3:reserved */ 237 //goto err_out; 238 info.free(); 239 return(null); 240 } 241 242 if(info.submaps>1){ 243 for(int i=0;i<vi.channels;i++){ 244 info.chmuxlist[i]=opb.read(4); 245 if(info.chmuxlist[i]>=info.submaps){ 246 //goto err_out; 247 info.free(); 248 return(null); 249 } 250 } 251 } 252 253 for(int i=0;i<info.submaps;i++){ 254 info.timesubmap[i]=opb.read(8); 255 if(info.timesubmap[i]>=vi.times){ 256 //goto err_out; 257 info.free(); 258 return(null); 259 } 260 info.floorsubmap[i]=opb.read(8); 261 if(info.floorsubmap[i]>=vi.floors){ 262 //goto err_out; 263 info.free(); 264 return(null); 265 } 266 info.residuesubmap[i]=opb.read(8); 267 if(info.residuesubmap[i]>=vi.residues){ 268 //goto err_out; 269 info.free(); 270 return(null); 271 } 272 } 273 return info; 274 //err_out: 275 //free_info(info); 276 //return(NULL); 277 } 278 279/* 280 // no time mapping implementation for now 281 static int seq=0; 282 int forward(Block vb, Object l){ 283 DspState vd=vb.vd; 284 Info vi=vd.vi; 285 LookMapping0 look=(LookMapping0)l; 286 InfoMapping0 info=look.map; 287 InfoMode mode=look.mode; 288 int n=vb.pcmend; 289 float[] window=vd.window[vb.W][vb.lW][vb.nW][mode.windowtype]; 290 291 float[][] pcmbundle=new float[vi.channles][]; 292 int[] nonzero=new int[vi.channels]; 293 294 // time domain pre-window: NONE IMPLEMENTED 295 296 // window the PCM data: takes PCM vector, vb; modifies PCM vector 297 298 for(int i=0;i<vi.channels;i++){ 299 float[] pcm=vb.pcm[i]; 300 for(int j=0;j<n;j++) 301 pcm[j]*=window[j]; 302 } 303 304 // time-domain post-window: NONE IMPLEMENTED 305 306 // transform the PCM data; takes PCM vector, vb; modifies PCM vector 307 // only MDCT right now.... 308 for(int i=0;i<vi.channels;i++){ 309 float[] pcm=vb.pcm[i]; 310 mdct_forward(vd.transform[vb.W][0],pcm,pcm); 311 } 312 313 { 314 float[] floor=_vorbis_block_alloc(vb,n*sizeof(float)/2); 315 316 for(int i=0;i<vi.channels;i++){ 317 float[] pcm=vb.pcm[i]; 318 float[] decay=look.decay[i]; 319 int submap=info.chmuxlist[i]; 320 321 // if some other mode/mapping was called last frame, our decay 322 // accumulator is out of date. Clear it. 323 //if(look.lastframe+1 != vb->sequence) 324 // memset(decay,0,n*sizeof(float)/2); 325 326 // perform psychoacoustics; do masking 327 _vp_compute_mask(look.psy_look[submap],pcm,floor,decay); 328 329 _analysis_output("mdct",seq,pcm,n/2,0,1); 330 _analysis_output("lmdct",seq,pcm,n/2,0,0); 331 _analysis_output("prefloor",seq,floor,n/2,0,1); 332 333 // perform floor encoding 334 nonzero[i]=look.floor_func[submap]. 335 forward(vb,look.floor_look[submap],floor,floor,look.floor_state[i]); 336 337 _analysis_output("floor",seq,floor,n/2,0,1); 338 339 // apply the floor, do optional noise levelling 340 _vp_apply_floor(look->psy_look+submap,pcm,floor); 341 342 _analysis_output("res",seq++,pcm,n/2,0,0); 343 } 344 345 // perform residue encoding with residue mapping; this is 346 // multiplexed. All the channels belonging to one submap are 347 // encoded (values interleaved), then the next submap, etc 348 349 for(int i=0;i<info.submaps;i++){ 350 int ch_in_bundle=0; 351 for(int j=0;j<vi.channels;j++){ 352 if(info.chmuxlist[j]==i && nonzero[j]==1){ 353 pcmbundle[ch_in_bundle++]=vb.pcm[j]; 354 } 355 } 356 look.residue_func[i].forward(vb,look.residue_look[i], pcmbundle,ch_in_bundle); 357 } 358 } 359 look.lastframe=vb.sequence; 360 return(0); 361 } 362*/ 363 364 float[][] pcmbundle=null; 365 int[] zerobundle=null; 366 int[] nonzero=null; 367 Object[] floormemo=null; 368 369 synchronized int inverse(Block vb, Object l){ 370 //System.err.println("Mapping0.inverse"); 371 DspState vd=vb.vd; 372 Info vi=vd.vi; 373 LookMapping0 look=(LookMapping0)l; 374 InfoMapping0 info=look.map; 375 InfoMode mode=look.mode; 376 int n=vb.pcmend=vi.blocksizes[vb.W]; 377 378 float[] window=vd.window[vb.W][vb.lW][vb.nW][mode.windowtype]; 379 // float[][] pcmbundle=new float[vi.channels][]; 380 // int[] nonzero=new int[vi.channels]; 381 if(pcmbundle==null || pcmbundle.length<vi.channels){ 382 pcmbundle=new float[vi.channels][]; 383 nonzero=new int[vi.channels]; 384 zerobundle=new int[vi.channels]; 385 floormemo=new Object[vi.channels]; 386 } 387 388 // time domain information decode (note that applying the 389 // information would have to happen later; we'll probably add a 390 // function entry to the harness for that later 391 // NOT IMPLEMENTED 392 393 // recover the spectral envelope; store it in the PCM vector for now 394 for(int i=0;i<vi.channels;i++){ 395 float[] pcm=vb.pcm[i]; 396 int submap=info.chmuxlist[i]; 397 398 floormemo[i]=look.floor_func[submap].inverse1(vb,look. 399 floor_look[submap], 400 floormemo[i] 401 ); 402 if(floormemo[i]!=null){ nonzero[i]=1; } 403 else{ nonzero[i]=0; } 404 for(int j=0; j<n/2; j++){ 405 pcm[j]=0; 406 } 407 408 //_analysis_output("ifloor",seq+i,pcm,n/2,0,1); 409 } 410 411 for(int i=0; i<info.coupling_steps; i++){ 412 if(nonzero[info.coupling_mag[i]]!=0 || 413 nonzero[info.coupling_ang[i]]!=0){ 414 nonzero[info.coupling_mag[i]]=1; 415 nonzero[info.coupling_ang[i]]=1; 416 } 417 } 418 419 // recover the residue, apply directly to the spectral envelope 420 421 for(int i=0;i<info.submaps;i++){ 422 int ch_in_bundle=0; 423 for(int j=0;j<vi.channels;j++){ 424 if(info.chmuxlist[j]==i){ 425 if(nonzero[j]!=0){ 426 zerobundle[ch_in_bundle]=1; 427 } 428 else{ 429 zerobundle[ch_in_bundle]=0; 430 } 431 pcmbundle[ch_in_bundle++]=vb.pcm[j]; 432 } 433 } 434 435 look.residue_func[i].inverse(vb,look.residue_look[i], 436 pcmbundle,zerobundle,ch_in_bundle); 437 } 438 439 440 for(int i=info.coupling_steps-1;i>=0;i--){ 441 float[] pcmM=vb.pcm[info.coupling_mag[i]]; 442 float[] pcmA=vb.pcm[info.coupling_ang[i]]; 443 444 for(int j=0;j<n/2;j++){ 445 float mag=pcmM[j]; 446 float ang=pcmA[j]; 447 448 if(mag>0){ 449 if(ang>0){ 450 pcmM[j]=mag; 451 pcmA[j]=mag-ang; 452 } 453 else{ 454 pcmA[j]=mag; 455 pcmM[j]=mag+ang; 456 } 457 } 458 else{ 459 if(ang>0){ 460 pcmM[j]=mag; 461 pcmA[j]=mag+ang; 462 } 463 else{ 464 pcmA[j]=mag; 465 pcmM[j]=mag-ang; 466 } 467 } 468 } 469 } 470 471// /* compute and apply spectral envelope */ 472 473 for(int i=0;i<vi.channels;i++){ 474 float[] pcm=vb.pcm[i]; 475 int submap=info.chmuxlist[i]; 476 look.floor_func[submap].inverse2(vb,look.floor_look[submap],floormemo[i],pcm); 477 } 478 479 // transform the PCM data; takes PCM vector, vb; modifies PCM vector 480 // only MDCT right now.... 481 482 for(int i=0;i<vi.channels;i++){ 483 float[] pcm=vb.pcm[i]; 484 //_analysis_output("out",seq+i,pcm,n/2,0,0); 485 ((Mdct)vd.transform[vb.W][0]).backward(pcm,pcm); 486 } 487 488 // now apply the decoded pre-window time information 489 // NOT IMPLEMENTED 490 491 // window the data 492 for(int i=0;i<vi.channels;i++){ 493 float[] pcm=vb.pcm[i]; 494 if(nonzero[i]!=0){ 495 for(int j=0;j<n;j++){ 496 pcm[j]*=window[j]; 497 } 498 } 499 else{ 500 for(int j=0;j<n;j++){ 501 pcm[j]=0.f; 502 } 503 } 504 //_analysis_output("final",seq++,pcm,n,0,0); 505 } 506 507 // now apply the decoded post-window time information 508 // NOT IMPLEMENTED 509 // all done! 510 return(0); 511 } 512 513 514 private static int ilog2(int v){ 515 int ret=0; 516 while(v>1){ 517 ret++; 518 v>>>=1; 519 } 520 return(ret); 521 } 522} 523 524class InfoMapping0{ 525 int submaps; // <= 16 526 int[] chmuxlist=new int[256]; // up to 256 channels in a Vorbis stream 527 528 int[] timesubmap=new int[16]; // [mux] 529 int[] floorsubmap=new int[16]; // [mux] submap to floors 530 int[] residuesubmap=new int[16];// [mux] submap to residue 531 int[] psysubmap=new int[16]; // [mux]; encode only 532 533 int coupling_steps; 534 int[] coupling_mag=new int[256]; 535 int[] coupling_ang=new int[256]; 536 537 void free(){ 538 chmuxlist=null; 539 timesubmap=null; 540 floorsubmap=null; 541 residuesubmap=null; 542 psysubmap=null; 543 544 coupling_mag=null; 545 coupling_ang=null; 546 } 547} 548 549class LookMapping0{ 550 InfoMode mode; 551 InfoMapping0 map; 552 Object[] time_look; 553 Object[] floor_look; 554 Object[] floor_state; 555 Object[] residue_look; 556 PsyLook[] psy_look; 557 558 FuncTime[] time_func; 559 FuncFloor[] floor_func; 560 FuncResidue[] residue_func; 561 562 int ch; 563 float[][] decay; 564 int lastframe; // if a different mode is called, we need to 565 // invalidate decay and floor state 566}