/* csvorbis * Copyright (C) 2000 ymnk, JCraft,Inc. * * Written by: 2000 ymnk<ymnk@jcraft.com> * Ported to C# from JOrbis by: Mark Crichton <crichton@gimp.org> * * Thanks go to the JOrbis team, for licencing the code under the * LGPL, making my job a lot easier. * * 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. */ using System; using System.Runtime.CompilerServices; using csogg; namespace csvorbis { class Residue0 : FuncResidue { override public void pack(Object vr, csBuffer opb) { InfoResidue0 info=(InfoResidue0)vr; int acc=0; opb.write(info.begin,24); opb.write(info.end,24); opb.write(info.grouping-1,24); /* residue vectors to group and code with a partitioned book */ opb.write(info.partitions-1,6); /* possible partition choices */ opb.write(info.groupbook,8); /* group huffman book */ /* secondstages is a bitmask; as encoding progresses pass by pass, a bitmask of one indicates this partition class has bits to write this pass */ for(int j=0;j<info.partitions;j++) { if(ilog(info.secondstages[j])>3) { /* yes, this is a minor hack due to not thinking ahead */ opb.write(info.secondstages[j],3); opb.write(1,1); opb.write(info.secondstages[j] >> 3,5); } else { opb.write(info.secondstages[j],4); /* trailing zero */ } acc+=icount(info.secondstages[j]); } for(int j=0;j<acc;j++) { opb.write(info.booklist[j],8); } } override public Object unpack(Info vi, csBuffer opb) { int acc=0; InfoResidue0 info=new InfoResidue0(); info.begin=opb.read(24); info.end=opb.read(24); info.grouping=opb.read(24)+1; info.partitions=opb.read(6)+1; info.groupbook=opb.read(8); for(int j=0;j<info.partitions;j++) { int cascade=opb.read(3); if(opb.read(1)!=0) { cascade|=(opb.read(5)<<3); } info.secondstages[j]=cascade; acc+=icount(cascade); } for(int j=0;j<acc;j++) { info.booklist[j]=opb.read(8); // if(info.booklist[j]==255)info.booklist[j]=-1; } if(info.groupbook>=vi.books) { free_info(info); return(null); } for(int j=0;j<acc;j++) { if(info.booklist[j]>=vi.books) { free_info(info); return(null); } } return(info); // errout: // free_info(info); // return(NULL); } override public Object look(DspState vd, InfoMode vm, Object vr) { InfoResidue0 info=(InfoResidue0)vr; LookResidue0 look=new LookResidue0(); int acc=0; int dim; int maxstage=0; look.info=info; look.map=vm.mapping; look.parts=info.partitions; look.fullbooks=vd.fullbooks; look.phrasebook=vd.fullbooks[info.groupbook]; dim=look.phrasebook.dim; look.partbooks=new int[look.parts][]; for(int j=0;j<look.parts;j++) { int stages=ilog(info.secondstages[j]); if(stages!=0) { if(stages>maxstage)maxstage=stages; look.partbooks[j]=new int[stages]; for(int k=0; k<stages; k++) { if((info.secondstages[j]&(1<<k))!=0) { look.partbooks[j][k]=info.booklist[acc++]; } } } } look.partvals=(int)Math.Round(Math.Pow(look.parts,dim)); look.stages=maxstage; look.decodemap=new int[look.partvals][]; for(int j=0;j<look.partvals;j++) { int val=j; int mult=look.partvals/look.parts; look.decodemap[j]=new int[dim]; for(int k=0;k<dim;k++) { int deco=val/mult; val-=deco*mult; mult/=look.parts; look.decodemap[j][k]=deco; } } return(look); } override public void free_info(Object i){} override public void free_look(Object i){} override public int forward(Block vb,Object vl, float[][] fin, int ch) { return 0; } static int[][][] partword=new int[2][][]; [MethodImpl(MethodImplOptions.Synchronized)] internal static int _01inverse(Block vb, Object vl, float[][] fin, int ch, int decodepart) { { int i,j,k,l,s; LookResidue0 look=(LookResidue0 )vl; InfoResidue0 info=look.info; // move all this setup out later int samples_per_partition=info.grouping; int partitions_per_word=look.phrasebook.dim; int n=info.end-info.begin; int partvals=n/samples_per_partition; int partwords=(partvals+partitions_per_word-1)/partitions_per_word; if(partword.Length<ch) { partword=new int[ch][][]; for(j=0;j<ch;j++) { partword[j]=new int[partwords][]; } } else { for(j=0;j<ch;j++) { if(partword[j]==null || partword[j].Length<partwords) partword[j]=new int[partwords][]; } } for(s=0;s<look.stages;s++) { // each loop decodes on partition codeword containing // partitions_pre_word partitions for(i=0,l=0;i<partvals;l++) { if(s==0) { // fetch the partition word for each channel for(j=0;j<ch;j++) { int temp=look.phrasebook.decode(vb.opb); if(temp==-1) { //goto eopbreak; return(0); } partword[j][l]=look.decodemap[temp]; if(partword[j][l]==null) { // goto errout; return(0); } } } // now we decode residual values for the partitions for(k=0;k<partitions_per_word && i<partvals;k++,i++) for(j=0;j<ch;j++) { int offset=info.begin+i*samples_per_partition; if((info.secondstages[partword[j][l][k]]&(1<<s))!=0) { CodeBook stagebook=look.fullbooks[look.partbooks[partword[j][l][k]][s]]; // CodeBook stagebook=look.partbooks[partword[j][l][k]][s]; if(stagebook!=null) { if(decodepart==0) { if(stagebook.decodevs_add(fin[j],offset,vb.opb,samples_per_partition)==-1) { // goto errout; return(0); } } else if(decodepart==1) { if(stagebook.decodev_add(fin[j], offset, vb.opb,samples_per_partition)==-1) { // goto errout; return(0); } } } } } } } return(0); } } internal static int _2inverse(Block vb, Object vl, float[][] fin, int ch) { int i,k,l,s; LookResidue0 look=(LookResidue0 )vl; InfoResidue0 info=look.info; // move all this setup out later int samples_per_partition=info.grouping; int partitions_per_word=look.phrasebook.dim; int n=info.end-info.begin; int partvals=n/samples_per_partition; int partwords=(partvals+partitions_per_word-1)/partitions_per_word; int[][] partword=new int[partwords][]; for(s=0;s<look.stages;s++) { for(i=0,l=0;i<partvals;l++) { if(s==0) { // fetch the partition word for each channel int temp=look.phrasebook.decode(vb.opb); if(temp==-1) { // goto eopbreak; return(0); } partword[l]=look.decodemap[temp]; if(partword[l]==null) { // goto errout; return(0); } } // now we decode residual values for the partitions for(k=0;k<partitions_per_word && i<partvals;k++,i++) { int offset=info.begin+i*samples_per_partition; if((info.secondstages[partword[l][k]]&(1<<s))!=0) { CodeBook stagebook=look.fullbooks[look.partbooks[partword[l][k]][s]]; if(stagebook!=null) { if(stagebook.decodevv_add(fin, offset, ch, vb.opb,samples_per_partition)==-1) { // goto errout; return(0); } } } } } } // errout: // eopbreak: return(0); } override public int inverse(Block vb, Object vl, float[][] fin, int[] nonzero, int ch) { //System.err.println("Residue0.inverse"); int used=0; for(int i=0;i<ch;i++) { if(nonzero[i]!=0) { fin[used++]=fin[i]; } } if(used!=0) return(_01inverse(vb, vl, fin, used, 0)); else return(0); } internal static int ilog(int v) { int ret=0; while(v!=0) { ret++; v = (int)((uint)v >> 1); } return(ret); } internal static int icount(int v) { int ret=0; while(v!=0) { ret+=(v&1); v = (int)((uint)v >> 1); } return(ret); } } class LookResidue0 { internal InfoResidue0 info; internal int map; internal int parts; internal int stages; internal CodeBook[] fullbooks; internal CodeBook phrasebook; internal int[][] partbooks; // CodeBook[][] partbooks; internal int partvals; internal int[][] decodemap; //internal int postbits; //internal int phrasebits; // int[][] frames; //internal int frames; } class InfoResidue0 { // block-partitioned VQ coded straight residue internal int begin; internal int end; // first stage (lossless partitioning) internal int grouping; // group n vectors per partition internal int partitions; // possible codebooks for a partition internal int groupbook; // huffbook for partitioning internal int[] secondstages=new int[64]; // expanded out to pointers in lookup internal int[] booklist=new int[256]; // list of second stage books // encode-only heuristic settings internal float[] entmax=new float[64]; // book entropy threshholds internal float[] ampmax=new float[64]; // book amp threshholds internal int[] subgrp=new int[64]; // book heuristic subgroup size internal int[] blimit=new int[64]; // subgroup position limits } }