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}