diff options
Diffstat (limited to 'songdbj/com/jcraft/jorbis/DspState.java')
-rw-r--r-- | songdbj/com/jcraft/jorbis/DspState.java | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/songdbj/com/jcraft/jorbis/DspState.java b/songdbj/com/jcraft/jorbis/DspState.java new file mode 100644 index 0000000000..5676f640c1 --- /dev/null +++ b/songdbj/com/jcraft/jorbis/DspState.java @@ -0,0 +1,459 @@ +/* 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; + +public class DspState{ + static final float M_PI=3.1415926539f; + static final int VI_TRANSFORMB=1; + static final int VI_WINDOWB=1; + + int analysisp; + Info vi; + int modebits; + + float[][] pcm; + //float[][] pcmret; + int pcm_storage; + int pcm_current; + int pcm_returned; + + float[] multipliers; + int envelope_storage; + int envelope_current; + + int eofflag; + + int lW; + int W; + int nW; + int centerW; + + long granulepos; + long sequence; + + long glue_bits; + long time_bits; + long floor_bits; + long res_bits; + + // local lookup storage +//!! Envelope ve=new Envelope(); // envelope +//float **window[2][2][2]; // block, leadin, leadout, type + float[][][][][] window; // block, leadin, leadout, type + //vorbis_look_transform **transform[2]; // block, type + Object[][] transform; + CodeBook[] fullbooks; + // backend lookups are tied to the mode, not the backend or naked mapping + Object[] mode; + + // local storage, only used on the encoding side. This way the + // application does not need to worry about freeing some packets' + // memory and not others'; packet storage is always tracked. + // Cleared next call to a _dsp_ function + byte[] header; + byte[] header1; + byte[] header2; + + public DspState(){ + transform=new Object[2][]; + window=new float[2][][][][]; + window[0]=new float[2][][][]; + window[0][0]=new float[2][][]; + window[0][1]=new float[2][][]; + window[0][0][0]=new float[2][]; + window[0][0][1]=new float[2][]; + window[0][1][0]=new float[2][]; + window[0][1][1]=new float[2][]; + window[1]=new float[2][][][]; + window[1][0]=new float[2][][]; + window[1][1]=new float[2][][]; + window[1][0][0]=new float[2][]; + window[1][0][1]=new float[2][]; + window[1][1][0]=new float[2][]; + window[1][1][1]=new float[2][]; + } + + private static int ilog2(int v){ + int ret=0; + while(v>1){ + ret++; + v>>>=1; + } + return(ret); + } + + static float[] window(int type, int window, int left, int right){ + float[] ret=new float[window]; + switch(type){ + case 0: + // The 'vorbis window' (window 0) is sin(sin(x)*sin(x)*2pi) + { + int leftbegin=window/4-left/2; + int rightbegin=window-window/4-right/2; + + for(int i=0;i<left;i++){ + float x=(float)((i+.5)/left*M_PI/2.); + x=(float)Math.sin(x); + x*=x; + x*=M_PI/2.; + x=(float)Math.sin(x); + ret[i+leftbegin]=x; + } + + for(int i=leftbegin+left;i<rightbegin;i++){ + ret[i]=1.f; + } + + for(int i=0;i<right;i++){ + float x=(float)((right-i-.5)/right*M_PI/2.); + x=(float)Math.sin(x); + x*=x; + x*=M_PI/2.; + x=(float)Math.sin(x); + ret[i+rightbegin]=x; + } + } + break; + default: + //free(ret); + return(null); + } + return(ret); + } + + // Analysis side code, but directly related to blocking. Thus it's + // here and not in analysis.c (which is for analysis transforms only). + // The init is here because some of it is shared + + int init(Info vi, boolean encp){ +//System.err.println("DspState.init: vi="+vi+", encp="+encp); + //memset(v,0,sizeof(vorbis_dsp_state)); + this.vi=vi; + modebits=ilog2(vi.modes); + + transform[0]=new Object[VI_TRANSFORMB]; + transform[1]=new Object[VI_TRANSFORMB]; + + // MDCT is tranform 0 + + transform[0][0]=new Mdct(); + transform[1][0]=new Mdct(); + ((Mdct)transform[0][0]).init(vi.blocksizes[0]); + ((Mdct)transform[1][0]).init(vi.blocksizes[1]); + + window[0][0][0]=new float[VI_WINDOWB][]; + window[0][0][1]=window[0][0][0]; + window[0][1][0]=window[0][0][0]; + window[0][1][1]=window[0][0][0]; + window[1][0][0]=new float[VI_WINDOWB][]; + window[1][0][1]=new float[VI_WINDOWB][]; + window[1][1][0]=new float[VI_WINDOWB][]; + window[1][1][1]=new float[VI_WINDOWB][]; + + for(int i=0;i<VI_WINDOWB;i++){ + window[0][0][0][i]= + window(i,vi.blocksizes[0],vi.blocksizes[0]/2,vi.blocksizes[0]/2); + window[1][0][0][i]= + window(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[0]/2); + window[1][0][1][i]= + window(i,vi.blocksizes[1],vi.blocksizes[0]/2,vi.blocksizes[1]/2); + window[1][1][0][i]= + window(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[0]/2); + window[1][1][1][i]= + window(i,vi.blocksizes[1],vi.blocksizes[1]/2,vi.blocksizes[1]/2); + } + +// if(encp){ // encode/decode differ here +// // finish the codebooks +// fullbooks=new CodeBook[vi.books]; +// for(int i=0;i<vi.books;i++){ +// fullbooks[i]=new CodeBook(); +// fullbooks[i].init_encode(vi.book_param[i]); +// } +// analysisp=1; +// } +// else{ + // finish the codebooks + fullbooks=new CodeBook[vi.books]; + for(int i=0;i<vi.books;i++){ + fullbooks[i]=new CodeBook(); + fullbooks[i].init_decode(vi.book_param[i]); + } +// } + + // initialize the storage vectors to a decent size greater than the + // minimum + + pcm_storage=8192; // we'll assume later that we have + // a minimum of twice the blocksize of + // accumulated samples in analysis + pcm=new float[vi.channels][]; + //pcmret=new float[vi.channels][]; + { + for(int i=0;i<vi.channels;i++){ + pcm[i]=new float[pcm_storage]; + } + } + + // all 1 (large block) or 0 (small block) + // explicitly set for the sake of clarity + lW=0; // previous window size + W=0; // current window size + + // all vector indexes; multiples of samples_per_envelope_step + centerW=vi.blocksizes[1]/2; + + pcm_current=centerW; + + // initialize all the mapping/backend lookups + mode=new Object[vi.modes]; + for(int i=0;i<vi.modes;i++){ + int mapnum=vi.mode_param[i].mapping; + int maptype=vi.map_type[mapnum]; + mode[i]=FuncMapping.mapping_P[maptype].look(this,vi.mode_param[i], + vi.map_param[mapnum]); + } + return(0); + } + + public int synthesis_init(Info vi){ + init(vi, false); + // Adjust centerW to allow an easier mechanism for determining output + pcm_returned=centerW; + centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4; + granulepos=-1; + sequence=-1; + return(0); + } + + DspState(Info vi){ + this(); + init(vi, false); + // Adjust centerW to allow an easier mechanism for determining output + pcm_returned=centerW; + centerW-= vi.blocksizes[W]/4+vi.blocksizes[lW]/4; + granulepos=-1; + sequence=-1; + } + + // Unike in analysis, the window is only partially applied for each + // block. The time domain envelope is not yet handled at the point of + // calling (as it relies on the previous block). + + public int synthesis_blockin(Block vb){ + // Shift out any PCM/multipliers that we returned previously + // centerW is currently the center of the last block added + if(centerW>vi.blocksizes[1]/2 && pcm_returned>8192){ + // don't shift too much; we need to have a minimum PCM buffer of + // 1/2 long block + + int shiftPCM=centerW-vi.blocksizes[1]/2; + shiftPCM=(pcm_returned<shiftPCM?pcm_returned:shiftPCM); + + pcm_current-=shiftPCM; + centerW-=shiftPCM; + pcm_returned-=shiftPCM; + if(shiftPCM!=0){ + for(int i=0;i<vi.channels;i++){ + System.arraycopy(pcm[i], shiftPCM, pcm[i], 0, pcm_current); + } + } + } + + lW=W; + W=vb.W; + nW=-1; + + glue_bits+=vb.glue_bits; + time_bits+=vb.time_bits; + floor_bits+=vb.floor_bits; + res_bits+=vb.res_bits; + + if(sequence+1 != vb.sequence)granulepos=-1; // out of sequence; lose count + + sequence=vb.sequence; + + { + int sizeW=vi.blocksizes[W]; + int _centerW=centerW+vi.blocksizes[lW]/4+sizeW/4; + int beginW=_centerW-sizeW/2; + int endW=beginW+sizeW; + int beginSl=0; + int endSl=0; + + // Do we have enough PCM/mult storage for the block? + if(endW>pcm_storage){ + // expand the storage + pcm_storage=endW+vi.blocksizes[1]; + for(int i=0;i<vi.channels;i++){ + float[] foo=new float[pcm_storage]; + System.arraycopy(pcm[i], 0, foo, 0, pcm[i].length); + pcm[i]=foo; + } + } + + // overlap/add PCM + switch(W){ + case 0: + beginSl=0; + endSl=vi.blocksizes[0]/2; + break; + case 1: + beginSl=vi.blocksizes[1]/4-vi.blocksizes[lW]/4; + endSl=beginSl+vi.blocksizes[lW]/2; + break; + } + + for(int j=0;j<vi.channels;j++){ + int _pcm=beginW; + // the overlap/add section + int i=0; + for(i=beginSl;i<endSl;i++){ + pcm[j][_pcm+i]+=vb.pcm[j][i]; + } + // the remaining section + for(;i<sizeW;i++){ + pcm[j][_pcm+i]=vb.pcm[j][i]; + } + } + + // track the frame number... This is for convenience, but also + // making sure our last packet doesn't end with added padding. If + // the last packet is partial, the number of samples we'll have to + // return will be past the vb->granulepos. + // + // This is not foolproof! It will be confused if we begin + // decoding at the last page after a seek or hole. In that case, + // we don't have a starting point to judge where the last frame + // is. For this reason, vorbisfile will always try to make sure + // it reads the last two marked pages in proper sequence + + if(granulepos==-1){ + granulepos=vb.granulepos; + } + else{ + granulepos+=(_centerW-centerW); + if(vb.granulepos!=-1 && granulepos!=vb.granulepos){ + if(granulepos>vb.granulepos && vb.eofflag!=0){ + // partial last frame. Strip the padding off + _centerW-=(granulepos-vb.granulepos); + }// else{ Shouldn't happen *unless* the bitstream is out of + // spec. Either way, believe the bitstream } + granulepos=vb.granulepos; + } + } + + // Update, cleanup + + centerW=_centerW; + pcm_current=endW; + if(vb.eofflag!=0)eofflag=1; + } + return(0); + } + + // pcm==NULL indicates we just want the pending samples, no more + public int synthesis_pcmout(float[][][] _pcm, int[] index){ + if(pcm_returned<centerW){ + if(_pcm!=null){ + for(int i=0;i<vi.channels;i++){ +// pcmret[i]=pcm[i]+v.pcm_returned; +//!!!!!!!! + index[i]=pcm_returned; + } + _pcm[0]=pcm; + } + return(centerW-pcm_returned); + } + return(0); + } + + public int synthesis_read(int bytes){ + if(bytes!=0 && pcm_returned+bytes>centerW)return(-1); + pcm_returned+=bytes; + return(0); + } + + public void clear(){ +/* + if(window[0][0][0]!=0){ + for(i=0;i<VI_WINDOWB;i++) + if(v->window[0][0][0][i])free(v->window[0][0][0][i]); + free(v->window[0][0][0]); + + for(j=0;j<2;j++) + for(k=0;k<2;k++){ + for(i=0;i<VI_WINDOWB;i++) + if(v->window[1][j][k][i])free(v->window[1][j][k][i]); + free(v->window[1][j][k]); + } + } + + if(v->pcm){ + for(i=0;i<vi->channels;i++) + if(v->pcm[i])free(v->pcm[i]); + free(v->pcm); + if(v->pcmret)free(v->pcmret); + } + if(v->multipliers)free(v->multipliers); + + _ve_envelope_clear(&v->ve); + if(v->transform[0]){ + mdct_clear(v->transform[0][0]); + free(v->transform[0][0]); + free(v->transform[0]); + } + if(v->transform[1]){ + mdct_clear(v->transform[1][0]); + free(v->transform[1][0]); + free(v->transform[1]); + } + + // free mode lookups; these are actually vorbis_look_mapping structs + if(vi){ + for(i=0;i<vi->modes;i++){ + int mapnum=vi->mode_param[i]->mapping; + int maptype=vi->map_type[mapnum]; + _mapping_P[maptype]->free_look(v->mode[i]); + } + // free codebooks + for(i=0;i<vi->books;i++) + vorbis_book_clear(v->fullbooks+i); + } + + if(v->mode)free(v->mode); + if(v->fullbooks)free(v->fullbooks); + + // free header, header1, header2 + if(v->header)free(v->header); + if(v->header1)free(v->header1); + if(v->header2)free(v->header2); + + memset(v,0,sizeof(vorbis_dsp_state)); + } +*/ +} +} |