/******************************************************************** * * * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. * * PLEASE READ THESE TERMS DISTRIBUTING. * * * * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 * * by Monty and The XIPHOPHORUS Company * * http://www.xiph.org/ * * * ******************************************************************** function: residue backend 0 implementation last mod: $Id: res0.c,v 1.15.4.1 2000/08/15 08:33:46 xiphmont Exp $ ********************************************************************/ /* Slow, slow, slow, simpleminded and did I mention it was slow? The encode/decode loops are coded for clarity and performance is not yet even a nagging little idea lurking in the shadows. Oh and BTW, it's slow. */ #include #include #include #include #include "vorbis/codec.h" #include "bitwise.h" #include "registry.h" #include "bookinternal.h" #include "sharedbook.h" #include "misc.h" #include "os.h" typedef struct { vorbis_info_residue0 *info; int map; int parts; codebook *phrasebook; codebook ***partbooks; int partvals; int **decodemap; } vorbis_look_residue0; void free_info(vorbis_info_residue *i){ if(i){ memset(i,0,sizeof(vorbis_info_residue0)); free(i); } } void free_look(vorbis_look_residue *i){ int j; if(i){ vorbis_look_residue0 *look=(vorbis_look_residue0 *)i; for(j=0;jparts;j++) if(look->partbooks[j])free(look->partbooks[j]); free(look->partbooks); for(j=0;jpartvals;j++) free(look->decodemap[j]); free(look->decodemap); memset(i,0,sizeof(vorbis_look_residue0)); free(i); } } void pack(vorbis_info_residue *vr,oggpack_buffer *opb){ vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; int j,acc=0; _oggpack_write(opb,info->begin,24); _oggpack_write(opb,info->end,24); _oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and code with a partitioned book */ _oggpack_write(opb,info->partitions-1,6); /* possible partition choices */ _oggpack_write(opb,info->groupbook,8); /* group huffman book */ for(j=0;jpartitions;j++){ _oggpack_write(opb,info->secondstages[j],4); /* zero *is* a valid choice */ acc+=info->secondstages[j]; } for(j=0;jbooklist[j],8); } /* vorbis_info is for range checking */ vorbis_info_residue *unpack(vorbis_info *vi,oggpack_buffer *opb){ int j,acc=0; vorbis_info_residue0 *info=calloc(1,sizeof(vorbis_info_residue0)); info->begin=_oggpack_read(opb,24); info->end=_oggpack_read(opb,24); info->grouping=_oggpack_read(opb,24)+1; info->partitions=_oggpack_read(opb,6)+1; info->groupbook=_oggpack_read(opb,8); for(j=0;jpartitions;j++){ acc+=info->secondstages[j]=_oggpack_read(opb,4); } for(j=0;jbooklist[j]=_oggpack_read(opb,8); if(info->groupbook>=vi->books)goto errout; for(j=0;jbooklist[j]>=vi->books)goto errout; return(info); errout: free_info(info); return(NULL); } vorbis_look_residue *look (vorbis_dsp_state *vd,vorbis_info_mode *vm, vorbis_info_residue *vr){ vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr; vorbis_look_residue0 *look=calloc(1,sizeof(vorbis_look_residue0)); int j,k,acc=0; int dim; look->info=info; look->map=vm->mapping; look->parts=info->partitions; look->phrasebook=vd->fullbooks+info->groupbook; dim=look->phrasebook->dim; look->partbooks=calloc(look->parts,sizeof(codebook **)); for(j=0;jparts;j++){ int stages=info->secondstages[j]; if(stages){ look->partbooks[j]=malloc(stages*sizeof(codebook *)); for(k=0;kpartbooks[j][k]=vd->fullbooks+info->booklist[acc++]; } } look->partvals=rint(pow(look->parts,dim)); look->decodemap=malloc(look->partvals*sizeof(int *)); for(j=0;jpartvals;j++){ long val=j; long mult=look->partvals/look->parts; look->decodemap[j]=malloc(dim*sizeof(int)); for(k=0;kparts; look->decodemap[j][k]=deco; } } return(look); } /* does not guard against invalid settings; eg, a subn of 16 and a subgroup request of 32. Max subn of 128 */ static int _testhack(double *vec,int n,vorbis_look_residue0 *look, int auxparts,int auxpartnum){ vorbis_info_residue0 *info=look->info; int i,j=0; double max,localmax=0.; double temp[128]; double entropy[8]; /* setup */ for(i=0;ilocalmax)localmax=temp[i]; max=localmax; for(i=0;i>=1; j++; if(n<=0)break; for(i=0;ilocalmax)localmax=temp[i]; } for(i=0;iblimit[i] && entropy[info->subgrp[i]]<=info->entmax[i] && max<=info->ampmax[i]) break; return(i); } static int _encodepart(oggpack_buffer *opb,double *vec, int n, int stages, codebook **books,int mode,int part){ int i,j,bits=0; for(j=0;jdim; int step=n/dim; for(i=0;idim; int step=n/dim; for(i=0;iinfo; /* move all this setup out later */ int samples_per_partition=info->grouping; int possible_partitions=info->partitions; int partitions_per_word=look->phrasebook->dim; int n=info->end-info->begin; long phrasebits=0,resbitsT=0; long *resbits=alloca(sizeof(long)*possible_partitions); long *resvals=alloca(sizeof(long)*possible_partitions); int partvals=n/samples_per_partition; int partwords=(partvals+partitions_per_word-1)/partitions_per_word; long **partword=_vorbis_block_alloc(vb,ch*sizeof(long *)); partvals=partwords*partitions_per_word; /* we find the patition type for each partition of each channel. We'll go back and do the interleaved encoding in a bit. For now, clarity */ memset(resbits,0,sizeof(long)*possible_partitions); memset(resvals,0,sizeof(long)*possible_partitions); for(i=0;ibegin,l=0;iend;i+=samples_per_partition,l++){ for(j=0;jbegin,l=0;iend;){ /* first we encode a partition codeword for each channel */ for(j=0;jphrasebook,val,&vb->opb); } /* now we encode interleaved residual values for the partitions */ for(k=0;kopb,in[j]+i,samples_per_partition, info->secondstages[partword[j][l]], look->partbooks[partword[j][l]],look->map,partword[j][l]); resvals[partword[j][l]]+=samples_per_partition; } } for(i=0;iend-info->begin),phrasebits,resbitsT); for(i=0;ipcmend/2; vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl; vorbis_info_residue0 *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=alloca(ch*sizeof(long *)); double *work=alloca(sizeof(double)*samples_per_partition); partvals=partwords*partitions_per_word; /* make sure we're zeroed up to the start */ for(j=0;jbegin); for(i=info->begin,l=0;iend;){ /* fetch the partition word for each channel */ for(j=0;jphrasebook,&vb->opb); if(temp==-1)goto eopbreak; partword[j]=look->decodemap[temp]; if(partword[j]==NULL)goto errout; } /* now we decode interleaved residual values for the partitions */ for(k=0;kopb,work,in[j]+i,samples_per_partition, info->secondstages[part], look->partbooks[part])==-1)goto eopbreak; } } eopbreak: if(i