]> Joshua Wise's Git repositories - patchfork.git/blob - jorbis/src/com/jcraft/jorbis/DspState.java
initial import from pitchfork-0.5.5
[patchfork.git] / jorbis / src / com / jcraft / jorbis / DspState.java
1 /* JOrbis
2  * Copyright (C) 2000 ymnk, JCraft,Inc.
3  *  
4  * Written by: 2000 ymnk<ymnk@jcraft.com>
5  *   
6  * Many thanks to 
7  *   Monty <monty@xiph.org> and 
8  *   The XIPHOPHORUS Company http://www.xiph.org/ .
9  * JOrbis has been based on their awesome works, Vorbis codec.
10  *   
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public License
13  * as published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15    
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU Library General Public License for more details.
20  * 
21  * You should have received a copy of the GNU Library General Public
22  * License along with this program; if not, write to the Free Software
23  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 package com.jcraft.jorbis;
27
28 public class DspState{
29   static final float M_PI=3.1415926539f;
30   static final int VI_TRANSFORMB=1;
31   static final int VI_WINDOWB=1;
32
33   int analysisp;
34   Info vi;
35   int modebits;
36
37   float[][] pcm;
38   //float[][] pcmret;
39   int      pcm_storage;
40   int      pcm_current;
41   int      pcm_returned;
42
43   float[]  multipliers;
44   int      envelope_storage;
45   int      envelope_current;
46
47   int  eofflag;
48
49   int lW;
50   int W;
51   int nW;
52   int centerW;
53
54   long granulepos;
55   long sequence;
56
57   long glue_bits;
58   long time_bits;
59   long floor_bits;
60   long res_bits;
61
62   // local lookup storage
63 //!!  Envelope ve=new Envelope(); // envelope
64 //float                **window[2][2][2]; // block, leadin, leadout, type
65   float[][][][][] window;                 // block, leadin, leadout, type
66   //vorbis_look_transform **transform[2];    // block, type 
67   Object[][] transform;
68   CodeBook[] fullbooks;
69   // backend lookups are tied to the mode, not the backend or naked mapping
70   Object[] mode;
71
72   // local storage, only used on the encoding side.  This way the
73   // application does not need to worry about freeing some packets'
74   // memory and not others'; packet storage is always tracked.
75   // Cleared next call to a _dsp_ function
76   byte[] header;
77   byte[] header1;
78   byte[] header2;
79
80   public DspState(){
81     transform=new Object[2][];
82     window=new float[2][][][][];
83     window[0]=new float[2][][][];
84     window[0][0]=new float[2][][];
85     window[0][1]=new float[2][][];
86     window[0][0][0]=new float[2][];
87     window[0][0][1]=new float[2][];
88     window[0][1][0]=new float[2][];
89     window[0][1][1]=new float[2][];
90     window[1]=new float[2][][][];
91     window[1][0]=new float[2][][];
92     window[1][1]=new float[2][][];
93     window[1][0][0]=new float[2][];
94     window[1][0][1]=new float[2][];
95     window[1][1][0]=new float[2][];
96     window[1][1][1]=new float[2][];
97   }
98
99   private static int ilog2(int v){
100     int ret=0;
101     while(v>1){
102       ret++;
103       v>>>=1;
104     }
105     return(ret);
106   }
107
108   static float[] window(int type, int window, int left, int right){
109     float[] ret=new float[window];
110     switch(type){
111     case 0:
112       // The 'vorbis window' (window 0) is sin(sin(x)*sin(x)*2pi)
113       {
114         int leftbegin=window/4-left/2;
115         int rightbegin=window-window/4-right/2;
116     
117         for(int i=0;i<left;i++){
118           float x=(float)((i+.5)/left*M_PI/2.);
119           x=(float)Math.sin(x);
120           x*=x;
121           x*=M_PI/2.;
122           x=(float)Math.sin(x);
123           ret[i+leftbegin]=x;
124         }
125       
126         for(int i=leftbegin+left;i<rightbegin;i++){
127           ret[i]=1.f;
128         }
129       
130         for(int i=0;i<right;i++){
131           float x=(float)((right-i-.5)/right*M_PI/2.);
132           x=(float)Math.sin(x);
133           x*=x;
134           x*=M_PI/2.;
135           x=(float)Math.sin(x);
136           ret[i+rightbegin]=x;
137         }
138       }
139       break;
140     default:
141       //free(ret);
142       return(null);
143     }
144     return(ret);
145   }
146
147   // Analysis side code, but directly related to blocking.  Thus it's
148   // here and not in analysis.c (which is for analysis transforms only).
149   // The init is here because some of it is shared
150
151   int init(Info vi, boolean encp){
152 //System.err.println("DspState.init: vi="+vi+", encp="+encp);
153     //memset(v,0,sizeof(vorbis_dsp_state));
154     this.vi=vi;
155     modebits=ilog2(vi.modes);
156
157     transform[0]=new Object[VI_TRANSFORMB];
158     transform[1]=new Object[VI_TRANSFORMB];
159
160     // MDCT is tranform 0
161
162     transform[0][0]=new Mdct();
163     transform[1][0]=new Mdct();
164     ((Mdct)transform[0][0]).init(vi.blocksizes[0]);
165     ((Mdct)transform[1][0]).init(vi.blocksizes[1]);
166
167     window[0][0][0]=new float[VI_WINDOWB][];
168     window[0][0][1]=window[0][0][0];
169     window[0][1][0]=window[0][0][0];
170     window[0][1][1]=window[0][0][0];
171     window[1][0][0]=new float[VI_WINDOWB][];
172     window[1][0][1]=new float[VI_WINDOWB][];
173     window[1][1][0]=new float[VI_WINDOWB][];
174     window[1][1][1]=new float[VI_WINDOWB][];
175
176     for(int i=0;i<VI_WINDOWB;i++){
177       window[0][0][0][i]=
178         window(i,vi.blocksizes[0],vi.blocksizes[0]/2,vi.blocksizes[0]/2);
179       window[1][0][0][i]=
180         window(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[0]/2);
181       window[1][0][1][i]=
182         window(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[1]/2);
183       window[1][1][0][i]=
184         window(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[0]/2);
185       window[1][1][1][i]=
186         window(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[1]/2);
187     }
188
189 //    if(encp){ // encode/decode differ here
190 //      // finish the codebooks
191 //      fullbooks=new CodeBook[vi.books];
192 //      for(int i=0;i<vi.books;i++){
193 //      fullbooks[i]=new CodeBook();
194 //      fullbooks[i].init_encode(vi.book_param[i]);
195 //      }
196 //      analysisp=1;
197 //    }
198 //    else{
199       // finish the codebooks
200       fullbooks=new CodeBook[vi.books];
201       for(int i=0;i<vi.books;i++){
202         fullbooks[i]=new CodeBook();
203         fullbooks[i].init_decode(vi.book_param[i]);
204       }
205 //    }
206
207     // initialize the storage vectors to a decent size greater than the
208     // minimum
209   
210     pcm_storage=8192; // we'll assume later that we have
211                         // a minimum of twice the blocksize of
212                         // accumulated samples in analysis
213     pcm=new float[vi.channels][];
214     //pcmret=new float[vi.channels][];
215     {
216       for(int i=0;i<vi.channels;i++){
217         pcm[i]=new float[pcm_storage];
218       }
219     }
220
221     // all 1 (large block) or 0 (small block)
222     // explicitly set for the sake of clarity
223     lW=0; // previous window size
224     W=0;  // current window size
225
226     // all vector indexes; multiples of samples_per_envelope_step
227     centerW=vi.blocksizes[1]/2;
228
229     pcm_current=centerW;
230
231     // initialize all the mapping/backend lookups
232     mode=new Object[vi.modes];
233     for(int i=0;i<vi.modes;i++){
234       int mapnum=vi.mode_param[i].mapping;
235       int maptype=vi.map_type[mapnum];
236       mode[i]=FuncMapping.mapping_P[maptype].look(this,vi.mode_param[i], 
237                                                   vi.map_param[mapnum]);
238     }
239     return(0);
240   }
241
242   public int synthesis_init(Info vi){
243     init(vi, false);
244     // Adjust centerW to allow an easier mechanism for determining output
245     pcm_returned=centerW;
246     centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4;
247     granulepos=-1;
248     sequence=-1;
249     return(0);
250   }
251
252   DspState(Info vi){
253     this();
254     init(vi, false);
255     // Adjust centerW to allow an easier mechanism for determining output
256     pcm_returned=centerW;
257     centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4;
258     granulepos=-1;
259     sequence=-1;
260   }
261
262   // Unike in analysis, the window is only partially applied for each
263   // block.  The time domain envelope is not yet handled at the point of
264   // calling (as it relies on the previous block).
265
266   public int synthesis_blockin(Block vb){
267     // Shift out any PCM/multipliers that we returned previously
268     // centerW is currently the center of the last block added
269     if(centerW>vi.blocksizes[1]/2 && pcm_returned>8192){
270       // don't shift too much; we need to have a minimum PCM buffer of
271       // 1/2 long block
272
273       int shiftPCM=centerW-vi.blocksizes[1]/2;
274       shiftPCM=(pcm_returned<shiftPCM?pcm_returned:shiftPCM);
275
276       pcm_current-=shiftPCM;
277       centerW-=shiftPCM;
278       pcm_returned-=shiftPCM;
279       if(shiftPCM!=0){
280         for(int i=0;i<vi.channels;i++){
281           System.arraycopy(pcm[i], shiftPCM, pcm[i], 0, pcm_current);
282         }
283       }
284     }
285
286     lW=W;
287     W=vb.W;
288     nW=-1;
289
290     glue_bits+=vb.glue_bits;
291     time_bits+=vb.time_bits;
292     floor_bits+=vb.floor_bits;
293     res_bits+=vb.res_bits;
294
295     if(sequence+1 != vb.sequence)granulepos=-1; // out of sequence; lose count
296
297     sequence=vb.sequence;
298
299     {
300       int sizeW=vi.blocksizes[W];
301       int _centerW=centerW+vi.blocksizes[lW]/4+sizeW/4;
302       int beginW=_centerW-sizeW/2;
303       int endW=beginW+sizeW;
304       int beginSl=0;
305       int endSl=0;
306
307       // Do we have enough PCM/mult storage for the block?
308       if(endW>pcm_storage){
309         // expand the storage
310         pcm_storage=endW+vi.blocksizes[1];
311         for(int i=0;i<vi.channels;i++){
312           float[] foo=new float[pcm_storage];
313           System.arraycopy(pcm[i], 0, foo, 0, pcm[i].length);
314           pcm[i]=foo;
315         }
316       }
317
318       // overlap/add PCM
319       switch(W){
320       case 0:
321         beginSl=0;
322         endSl=vi.blocksizes[0]/2;
323         break;
324       case 1:
325         beginSl=vi.blocksizes[1]/4-vi.blocksizes[lW]/4;
326         endSl=beginSl+vi.blocksizes[lW]/2;
327         break;
328       }
329
330       for(int j=0;j<vi.channels;j++){
331         int _pcm=beginW;
332         // the overlap/add section
333         int i=0;
334         for(i=beginSl;i<endSl;i++){
335           pcm[j][_pcm+i]+=vb.pcm[j][i];
336         }
337         // the remaining section
338         for(;i<sizeW;i++){
339           pcm[j][_pcm+i]=vb.pcm[j][i];
340         }
341       }
342
343       // track the frame number... This is for convenience, but also
344       // making sure our last packet doesn't end with added padding.  If
345       // the last packet is partial, the number of samples we'll have to
346       // return will be past the vb->granulepos.
347       //       
348       // This is not foolproof!  It will be confused if we begin
349       // decoding at the last page after a seek or hole.  In that case,
350       // we don't have a starting point to judge where the last frame
351       // is.  For this reason, vorbisfile will always try to make sure
352       // it reads the last two marked pages in proper sequence
353
354       if(granulepos==-1){
355         granulepos=vb.granulepos;
356       }
357       else{
358         granulepos+=(_centerW-centerW);
359         if(vb.granulepos!=-1 && granulepos!=vb.granulepos){
360           if(granulepos>vb.granulepos && vb.eofflag!=0){
361             // partial last frame.  Strip the padding off
362             _centerW-=(granulepos-vb.granulepos);
363           }// else{ Shouldn't happen *unless* the bitstream is out of
364            // spec.  Either way, believe the bitstream }
365           granulepos=vb.granulepos;
366         }
367       }
368
369       // Update, cleanup
370
371       centerW=_centerW;
372       pcm_current=endW;
373       if(vb.eofflag!=0)eofflag=1;
374     }
375     return(0);
376   }
377
378   // pcm==NULL indicates we just want the pending samples, no more
379   public int synthesis_pcmout(float[][][] _pcm, int[] index){
380     if(pcm_returned<centerW){
381       if(_pcm!=null){
382         for(int i=0;i<vi.channels;i++){
383 //        pcmret[i]=pcm[i]+v.pcm_returned;
384 //!!!!!!!!
385           index[i]=pcm_returned;
386         }
387         _pcm[0]=pcm;
388       }
389       return(centerW-pcm_returned);
390     }
391     return(0);
392   }
393
394   public int synthesis_read(int bytes){
395     if(bytes!=0 && pcm_returned+bytes>centerW)return(-1);
396     pcm_returned+=bytes;
397     return(0);
398   }
399
400   public void clear(){
401 /*
402     if(window[0][0][0]!=0){
403       for(i=0;i<VI_WINDOWB;i++)
404         if(v->window[0][0][0][i])free(v->window[0][0][0][i]);
405       free(v->window[0][0][0]);
406
407       for(j=0;j<2;j++)
408         for(k=0;k<2;k++){
409           for(i=0;i<VI_WINDOWB;i++)
410             if(v->window[1][j][k][i])free(v->window[1][j][k][i]);
411           free(v->window[1][j][k]);
412         }
413     }
414     
415     if(v->pcm){
416       for(i=0;i<vi->channels;i++)
417         if(v->pcm[i])free(v->pcm[i]);
418       free(v->pcm);
419       if(v->pcmret)free(v->pcmret);
420     }
421     if(v->multipliers)free(v->multipliers);
422
423     _ve_envelope_clear(&v->ve);
424     if(v->transform[0]){
425       mdct_clear(v->transform[0][0]);
426       free(v->transform[0][0]);
427       free(v->transform[0]);
428     }
429     if(v->transform[1]){
430       mdct_clear(v->transform[1][0]);
431       free(v->transform[1][0]);
432       free(v->transform[1]);
433     }
434
435     // free mode lookups; these are actually vorbis_look_mapping structs
436     if(vi){
437       for(i=0;i<vi->modes;i++){
438         int mapnum=vi->mode_param[i]->mapping;
439         int maptype=vi->map_type[mapnum];
440         _mapping_P[maptype]->free_look(v->mode[i]);
441       }
442       // free codebooks
443       for(i=0;i<vi->books;i++)
444         vorbis_book_clear(v->fullbooks+i);
445     }
446
447     if(v->mode)free(v->mode);    
448     if(v->fullbooks)free(v->fullbooks);
449
450     // free header, header1, header2
451     if(v->header)free(v->header);
452     if(v->header1)free(v->header1);
453     if(v->header2)free(v->header2);
454
455     memset(v,0,sizeof(vorbis_dsp_state));
456   }
457 */
458 }
459 }
This page took 0.048616 seconds and 4 git commands to generate.