summaryrefslogtreecommitdiffstats
path: root/songdbj/com/jcraft/jorbis/DspState.java
diff options
context:
space:
mode:
Diffstat (limited to 'songdbj/com/jcraft/jorbis/DspState.java')
-rw-r--r--songdbj/com/jcraft/jorbis/DspState.java459
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));
+ }
+*/
+}
+}