int vorbis_synthesis(vorbis_block *vb,ogg_packet *op,int decodep){ vorbis_dsp_state *vd=vb->vd; private_state *b=(private_state *)vd->backend_state; vorbis_info *vi=vd->vi; codec_setup_info *ci=(codec_setup_info *)vi->codec_setup; oggpack_buffer *opb=&vb->opb; int type,mode,i; /* first things first. Make sure decode is ready */ _vorbis_block_ripcord(vb); oggpack_readinit(opb,op->packet); /* Check the packet type */ if(oggpack_read(opb,1)!=0){ /* Oops. This is not an audio data packet */ return(OV_ENOTAUDIO); } /* read our mode and pre/post windowsize */ mode=oggpack_read(opb,b->modebits); if(mode==-1)return(OV_EBADPACKET); vb->mode=mode; vb->W=ci->mode_param[mode]->blockflag; if(vb->W){ vb->lW=oggpack_read(opb,1); vb->nW=oggpack_read(opb,1); if(vb->nW==-1) return(OV_EBADPACKET); }else{ vb->lW=0; vb->nW=0; } /* more setup */ vb->granulepos=op->granulepos; vb->sequence=op->packetno-3; /* first block is third packet */ vb->eofflag=op->e_o_s; if(decodep){ /* alloc pcm passback storage */ vb->pcmend=ci->blocksizes[vb->W]; vb->pcm=(ogg_int32_t **)_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); for(i=0;i<vi->channels;i++) vb->pcm[i]=(ogg_int32_t *)_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); /* unpack_header enforces range checking */ type=ci->map_type[ci->mode_param[mode]->mapping]; return(_mapping_P[type]->inverse(vb,b->mode[mode])); }else{ /* no pcm */ vb->pcmend=0; vb->pcm=NULL; return(0); } }
static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){ vorbis_look_floor0 *look=(vorbis_look_floor0 *)i; vorbis_info_floor0 *info=look->vi; int j,k; int ampraw=oggpack_read(&vb->opb,info->ampbits); if(ampraw>0){ /* also handles the -1 out of data case */ long maxval=(1<<info->ampbits)-1; float amp=(float)ampraw/maxval*info->ampdB; int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks)); if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */ codec_setup_info *ci=vb->vd->vi->codec_setup; codebook *b=ci->fullbooks+info->books[booknum]; float last=0.f; /* the additional b->dim is a guard against any possible stack smash; b->dim is provably more than we can overflow the vector */ float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1)); for(j=0;j<look->m;j+=b->dim) if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop; for(j=0;j<look->m;){ for(k=0;k<b->dim;k++,j++)lsp[j]+=last; last=lsp[j-1]; } lsp[look->m]=amp; return(lsp); } } eop: return(NULL); }
/* a truncated packet here just means 'stop working'; it's not an error */ static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl, ogg_int32_t **in,int ch, long (*decodepart)(codebook *, ogg_int32_t *, oggpack_buffer *,int,int)){ long i,j,k,l,s; 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 max=vb->pcmend>>1; int end=(info->end<max?info->end:max); int n=end-info->begin; if(n>0){ int partvals=n/samples_per_partition; int partwords=(partvals+partitions_per_word-1)/partitions_per_word; int ***partword=(int ***)alloca(ch*sizeof(*partword)); for(j=0;j<ch;j++) partword[j]=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword[j])); 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=vorbis_book_decode(look->phrasebook,&vb->opb); if(temp==-1 || temp>=info->partvals)goto eopbreak; partword[j][l]=look->decodemap[temp]; if(partword[j][l]==NULL)goto errout; } } /* 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++){ long offset=info->begin+i*samples_per_partition; if(info->secondstages[partword[j][l][k]]&(1<<s)){ codebook *stagebook=look->partbooks[partword[j][l][k]][s]; if(stagebook){ if(decodepart(stagebook,in[j]+offset,&vb->opb, samples_per_partition,-8)==-1)goto eopbreak; } } } } } } errout: eopbreak: return(0); }
/* duplicate code here as speed is somewhat more important */ int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl, ogg_int32_t **in,int *nonzero,int ch){ long i,k,l,s; 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 max=(vb->pcmend*ch)>>1; int end=(info->end<max?info->end:max); int n=end-info->begin; if(n>0){ int partvals=n/samples_per_partition; int partwords=(partvals+partitions_per_word-1)/partitions_per_word; int **partword=(int **)_vorbis_block_alloc(vb,partwords*sizeof(*partword)); int beginoff=info->begin/ch; for(i=0;i<ch;i++)if(nonzero[i])break; if(i==ch)return(0); /* no nonzero vectors */ samples_per_partition/=ch; for(s=0;s<look->stages;s++){ for(i=0,l=0;i<partvals;l++){ if(s==0){ /* fetch the partition word */ int temp=vorbis_book_decode(look->phrasebook,&vb->opb); if(temp==-1 || temp>=info->partvals)goto eopbreak; partword[l]=look->decodemap[temp]; if(partword[l]==NULL)goto errout; } /* now we decode residual values for the partitions */ for(k=0;k<partitions_per_word && i<partvals;k++,i++) if(info->secondstages[partword[l][k]]&(1<<s)){ codebook *stagebook=look->partbooks[partword[l][k]][s]; if(stagebook){ if(vorbis_book_decodevv_add(stagebook,in, i*samples_per_partition+beginoff,ch, &vb->opb, samples_per_partition,-8)==-1) goto eopbreak; } } } } } errout: eopbreak: return(0); }
void bitbuf_write(vorbis_bitbuffer *vbb,unsigned long word,int length){ vorbis_block *vb=vbb->vb; if(vbb->ptr>=_VBB_ALLOCSIZE){ vbb->last->next=_vorbis_block_alloc(vb,sizeof(vorbis_bitbuffer_chain)); vbb->last=vbb->last->next; vbb->last->next=0; /* overengineering */ vbb->ptr=0; } vbb->last->words[vbb->ptr]=word; vbb->last->bits[vbb->ptr++]=length; }
int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor1 *look, int *A,int *B, int del){ long i; long posts=look->posts; int *output=NULL; if(A && B){ output=_vorbis_block_alloc(vb,sizeof(*output)*posts); for(i=0;i<posts;i++){ output[i]=((65536-del)*(A[i]&0x7fff)+del*(B[i]&0x7fff)+32768)>>16; if(A[i]&0x8000 && B[i]&0x8000)output[i]|=0x8000; } }
int *floor1_fit(vorbis_block *vb,vorbis_look_floor1 *look, const float *logmdct, /* in */ const float *logmask){ long i,j; vorbis_info_floor1 *info=look->vi; long n=look->n; long posts=look->posts; long nonzero=0; lsfit_acc fits[VIF_POSIT+1]; int fit_valueA[VIF_POSIT+2]; /* index by range list position */ int fit_valueB[VIF_POSIT+2]; /* index by range list position */ int loneighbor[VIF_POSIT+2]; /* sorted index of range list position (+2) */ int hineighbor[VIF_POSIT+2]; int *output=NULL; int memo[VIF_POSIT+2]; for(i=0;i<posts;i++)fit_valueA[i]=-200; /* mark all unused */ for(i=0;i<posts;i++)fit_valueB[i]=-200; /* mark all unused */ for(i=0;i<posts;i++)loneighbor[i]=0; /* 0 for the implicit 0 post */ for(i=0;i<posts;i++)hineighbor[i]=1; /* 1 for the implicit post at n */ for(i=0;i<posts;i++)memo[i]=-1; /* no neighbor yet */ /* quantize the relevant floor points and collect them into line fit structures (one per minimal division) at the same time */ if(posts==0){ nonzero+=accumulate_fit(logmask,logmdct,0,n,fits,n,info); }else{ for(i=0;i<posts-1;i++) nonzero+=accumulate_fit(logmask,logmdct,look->sorted_index[i], look->sorted_index[i+1],fits+i, n,info); } if(nonzero){ /* start by fitting the implicit base case.... */ int y0=-200; int y1=-200; fit_line(fits,posts-1,&y0,&y1); fit_valueA[0]=y0; fit_valueB[0]=y0; fit_valueB[1]=y1; fit_valueA[1]=y1; /* Non degenerate case */ /* start progressive splitting. This is a greedy, non-optimal algorithm, but simple and close enough to the best answer. */ for(i=2;i<posts;i++){ int sortpos=look->reverse_index[i]; int ln=loneighbor[sortpos]; int hn=hineighbor[sortpos]; /* eliminate repeat searches of a particular range with a memo */ if(memo[ln]!=hn){ /* haven't performed this error search yet */ int lsortpos=look->reverse_index[ln]; int hsortpos=look->reverse_index[hn]; memo[ln]=hn; { /* A note: we want to bound/minimize *local*, not global, error */ int lx=info->postlist[ln]; int hx=info->postlist[hn]; int ly=post_Y(fit_valueA,fit_valueB,ln); int hy=post_Y(fit_valueA,fit_valueB,hn); if(ly==-1 || hy==-1){ exit(1); } if(inspect_error(lx,hx,ly,hy,logmask,logmdct,info)){ /* outside error bounds/begin search area. Split it. */ int ly0=-200; int ly1=-200; int hy0=-200; int hy1=-200; fit_line(fits+lsortpos,sortpos-lsortpos,&ly0,&ly1); fit_line(fits+sortpos,hsortpos-sortpos,&hy0,&hy1); /* store new edge values */ fit_valueB[ln]=ly0; if(ln==0)fit_valueA[ln]=ly0; fit_valueA[i]=ly1; fit_valueB[i]=hy0; fit_valueA[hn]=hy1; if(hn==1)fit_valueB[hn]=hy1; if(ly1>=0 || hy0>=0){ /* store new neighbor values */ for(j=sortpos-1;j>=0;j--) if(hineighbor[j]==hn) hineighbor[j]=i; else break; for(j=sortpos+1;j<posts;j++) if(loneighbor[j]==ln) loneighbor[j]=i; else break; } }else{ fit_valueA[i]=-200; fit_valueB[i]=-200; } } } } output=_vorbis_block_alloc(vb,sizeof(*output)*posts); output[0]=post_Y(fit_valueA,fit_valueB,0); output[1]=post_Y(fit_valueA,fit_valueB,1); /* fill in posts marked as not using a fit; we will zero back out to 'unused' when encoding them so long as curve interpolation doesn't force them into use */ for(i=2;i<posts;i++){ int ln=look->loneighbor[i-2]; int hn=look->hineighbor[i-2]; int x0=info->postlist[ln]; int x1=info->postlist[hn]; int y0=output[ln]; int y1=output[hn]; int predicted=render_point(x0,x1,y0,y1,info->postlist[i]); int vx=post_Y(fit_valueA,fit_valueB,i); if(vx>=0 && predicted!=vx){ output[i]=vx; }else{ output[i]= predicted|0x8000; } } } return(output); }
/* do the deltas, envelope shaping, pre-echo and determine the size of the next block on which to continue analysis */ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){ int i; vorbis_info *vi=v->vi; codec_setup_info *ci=vi->codec_setup; private_state *b=v->backend_state; vorbis_look_psy_global *g=b->psy_g_look; long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext; vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; /* check to see if we're started... */ if(!v->preextrapolate)return(0); /* check to see if we're done... */ if(v->eofflag==-1)return(0); /* By our invariant, we have lW, W and centerW set. Search for the next boundary so we can determine nW (the next window size) which lets us compute the shape of the current block's window */ /* we do an envelope search even on a single blocksize; we may still be throwing more bits at impulses, and envelope search handles marking impulses too. */ { long bp=_ve_envelope_search(v); if(bp==-1){ if(v->eofflag==0)return(0); /* not enough data currently to search for a full long block */ v->nW=0; }else{ if(ci->blocksizes[0]==ci->blocksizes[1]) v->nW=0; else v->nW=bp; } } centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4; { /* center of next block + next block maximum right side. */ long blockbound=centerNext+ci->blocksizes[v->nW]/2; if(v->pcm_current<blockbound)return(0); /* not enough data yet; although this check is less strict that the _ve_envelope_search, the search is not run if we only use one block size */ } /* fill in the block. Note that for a short window, lW and nW are *short* regardless of actual settings in the stream */ _vorbis_block_ripcord(vb); vb->lW=v->lW; vb->W=v->W; vb->nW=v->nW; if(v->W){ if(!v->lW || !v->nW){ vbi->blocktype=BLOCKTYPE_TRANSITION; /*fprintf(stderr,"-");*/ }else{ vbi->blocktype=BLOCKTYPE_LONG; /*fprintf(stderr,"_");*/ } }else{ if(_ve_envelope_mark(v)){ vbi->blocktype=BLOCKTYPE_IMPULSE; /*fprintf(stderr,"|");*/ }else{ vbi->blocktype=BLOCKTYPE_PADDING; /*fprintf(stderr,".");*/ } } vb->vd=v; vb->sequence=v->sequence++; vb->granulepos=v->granulepos; vb->pcmend=ci->blocksizes[v->W]; /* copy the vectors; this uses the local storage in vb */ /* this tracks 'strongest peak' for later psychoacoustics */ /* moved to the global psy state; clean this mess up */ if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax; g->ampmax=_vp_ampmax_decay(g->ampmax,v); vbi->ampmax=g->ampmax; vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels); for(i=0;i<vi->channels;i++){ vbi->pcmdelay[i]= _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i])); vb->pcm[i]=vbi->pcmdelay[i]+beginW; /* before we added the delay vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i])); */ } /* handle eof detection: eof==0 means that we've not yet received EOF eof>0 marks the last 'real' sample in pcm[] eof<0 'no more to do'; doesn't get here */ if(v->eofflag){ if(v->centerW>=v->eofflag){ v->eofflag=-1; vb->eofflag=1; return(1); } } /* advance storage vectors and clean up */ { int new_centerNext=ci->blocksizes[1]/2; int movementW=centerNext-new_centerNext; if(movementW>0){ _ve_envelope_shift(b->ve,movementW); v->pcm_current-=movementW; for(i=0;i<vi->channels;i++) memmove(v->pcm[i],v->pcm[i]+movementW, v->pcm_current*sizeof(*v->pcm[i])); v->lW=v->W; v->W=v->nW; v->centerW=new_centerNext; if(v->eofflag){ v->eofflag-=movementW; if(v->eofflag<=0)v->eofflag=-1; /* do not add padding to end of stream! */ if(v->centerW>=v->eofflag){ v->granulepos+=movementW-(v->centerW-v->eofflag); }else{ v->granulepos+=movementW; } }else{ v->granulepos+=movementW; } } } /* done */ return(1); }
static int mapping0_forward(vorbis_block *vb){ vorbis_dsp_state *vd=vb->vd; vorbis_info *vi=vd->vi; codec_setup_info *ci=vi->codec_setup; private_state *b=vb->vd->backend_state; vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; int n=vb->pcmend; int i,j,k; int *nonzero = alloca(sizeof(*nonzero)*vi->channels); float **gmdct = _vorbis_block_alloc(vb,vi->channels*sizeof(*gmdct)); int **ilogmaskch= _vorbis_block_alloc(vb,vi->channels*sizeof(*ilogmaskch)); int ***floor_posts = _vorbis_block_alloc(vb,vi->channels*sizeof(*floor_posts)); float global_ampmax=vbi->ampmax; float *local_ampmax=alloca(sizeof(*local_ampmax)*vi->channels); int blocktype=vbi->blocktype; int modenumber=vb->W; vorbis_info_mapping0 *info=ci->map_param[modenumber]; vorbis_look_psy *psy_look= b->psy+blocktype+(vb->W?2:0); vb->mode=modenumber; for(i=0;i<vi->channels;i++){ float scale=4.f/n; float scale_dB; float *pcm =vb->pcm[i]; float *logfft =pcm; gmdct[i]=_vorbis_block_alloc(vb,n/2*sizeof(**gmdct)); scale_dB=todB(&scale) + .345; /* + .345 is a hack; the original todB estimation used on IEEE 754 compliant machines had a bug that returned dB values about a third of a decibel too high. The bug was harmless because tunings implicitly took that into account. However, fixing the bug in the estimator requires changing all the tunings as well. For now, it's easier to sync things back up here, and recalibrate the tunings in the next major model upgrade. */ #if 0 if(vi->channels==2) if(i==0) _analysis_output("pcmL",seq,pcm,n,0,0,total-n/2); else _analysis_output("pcmR",seq,pcm,n,0,0,total-n/2); #endif /* window the PCM data */ _vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW); #if 0 if(vi->channels==2) if(i==0) _analysis_output("windowedL",seq,pcm,n,0,0,total-n/2); else _analysis_output("windowedR",seq,pcm,n,0,0,total-n/2); #endif /* transform the PCM data */ /* only MDCT right now.... */ mdct_forward(b->transform[vb->W][0],pcm,gmdct[i]); /* FFT yields more accurate tonal estimation (not phase sensitive) */ drft_forward(&b->fft_look[vb->W],pcm); logfft[0]=scale_dB+todB(pcm) + .345; /* + .345 is a hack; the original todB estimation used on IEEE 754 compliant machines had a bug that returned dB values about a third of a decibel too high. The bug was harmless because tunings implicitly took that into account. However, fixing the bug in the estimator requires changing all the tunings as well. For now, it's easier to sync things back up here, and recalibrate the tunings in the next major model upgrade. */ local_ampmax[i]=logfft[0]; for(j=1;j<n-1;j+=2){ float temp=pcm[j]*pcm[j]+pcm[j+1]*pcm[j+1]; temp=logfft[(j+1)>>1]=scale_dB+.5f*todB(&temp) + .345; /* + .345 is a hack; the original todB estimation used on IEEE 754 compliant machines had a bug that returned dB values about a third of a decibel too high. The bug was harmless because tunings implicitly took that into account. However, fixing the bug in the estimator requires changing all the tunings as well. For now, it's easier to sync things back up here, and recalibrate the tunings in the next major model upgrade. */ if(temp>local_ampmax[i])local_ampmax[i]=temp; } if(local_ampmax[i]>0.f)local_ampmax[i]=0.f; if(local_ampmax[i]>global_ampmax)global_ampmax=local_ampmax[i]; #if 0 if(vi->channels==2){ if(i==0){ _analysis_output("fftL",seq,logfft,n/2,1,0,0); }else{ _analysis_output("fftR",seq,logfft,n/2,1,0,0); } } #endif } { float *noise = _vorbis_block_alloc(vb,n/2*sizeof(*noise)); float *tone = _vorbis_block_alloc(vb,n/2*sizeof(*tone)); for(i=0;i<vi->channels;i++){ /* the encoder setup assumes that all the modes used by any specific bitrate tweaking use the same floor */ int submap=info->chmuxlist[i]; /* the following makes things clearer to *me* anyway */ float *mdct =gmdct[i]; float *logfft =vb->pcm[i]; float *logmdct =logfft+n/2; float *logmask =logfft; vb->mode=modenumber; floor_posts[i]=_vorbis_block_alloc(vb,PACKETBLOBS*sizeof(**floor_posts)); memset(floor_posts[i],0,sizeof(**floor_posts)*PACKETBLOBS); for(j=0;j<n/2;j++) logmdct[j]=todB(mdct+j) + .345; /* + .345 is a hack; the original todB estimation used on IEEE 754 compliant machines had a bug that returned dB values about a third of a decibel too high. The bug was harmless because tunings implicitly took that into account. However, fixing the bug in the estimator requires changing all the tunings as well. For now, it's easier to sync things back up here, and recalibrate the tunings in the next major model upgrade. */ #if 0 if(vi->channels==2){ if(i==0) _analysis_output("mdctL",seq,logmdct,n/2,1,0,0); else _analysis_output("mdctR",seq,logmdct,n/2,1,0,0); }else{ _analysis_output("mdct",seq,logmdct,n/2,1,0,0); } #endif /* first step; noise masking. Not only does 'noise masking' give us curves from which we can decide how much resolution to give noise parts of the spectrum, it also implicitly hands us a tonality estimate (the larger the value in the 'noise_depth' vector, the more tonal that area is) */ _vp_noisemask(psy_look, logmdct, noise); /* noise does not have by-frequency offset bias applied yet */ #if 0 if(vi->channels==2){ if(i==0) _analysis_output("noiseL",seq,noise,n/2,1,0,0); else _analysis_output("noiseR",seq,noise,n/2,1,0,0); } #endif /* second step: 'all the other crap'; all the stuff that isn't computed/fit for bitrate management goes in the second psy vector. This includes tone masking, peak limiting and ATH */ _vp_tonemask(psy_look, logfft, tone, global_ampmax, local_ampmax[i]); #if 0 if(vi->channels==2){ if(i==0) _analysis_output("toneL",seq,tone,n/2,1,0,0); else _analysis_output("toneR",seq,tone,n/2,1,0,0); } #endif /* third step; we offset the noise vectors, overlay tone masking. We then do a floor1-specific line fit. If we're performing bitrate management, the line fit is performed multiple times for up/down tweakage on demand. */ #if 0 { float aotuv[psy_look->n]; #endif _vp_offset_and_mix(psy_look, noise, tone, 1, logmask, mdct, logmdct); #if 0 if(vi->channels==2){ if(i==0) _analysis_output("aotuvM1_L",seq,aotuv,psy_look->n,1,1,0); else _analysis_output("aotuvM1_R",seq,aotuv,psy_look->n,1,1,0); } } #endif #if 0 if(vi->channels==2){ if(i==0) _analysis_output("mask1L",seq,logmask,n/2,1,0,0); else _analysis_output("mask1R",seq,logmask,n/2,1,0,0); } #endif /* this algorithm is hardwired to floor 1 for now; abort out if we're *not* floor1. This won't happen unless someone has broken the encode setup lib. Guard it anyway. */ if(ci->floor_type[info->floorsubmap[submap]]!=1)return(-1); floor_posts[i][PACKETBLOBS/2]= floor1_fit(vb,b->flr[info->floorsubmap[submap]], logmdct, logmask); /* are we managing bitrate? If so, perform two more fits for later rate tweaking (fits represent hi/lo) */ if(vorbis_bitrate_managed(vb) && floor_posts[i][PACKETBLOBS/2]){ /* higher rate by way of lower noise curve */ _vp_offset_and_mix(psy_look, noise, tone, 2, logmask, mdct, logmdct); #if 0 if(vi->channels==2){ if(i==0) _analysis_output("mask2L",seq,logmask,n/2,1,0,0); else _analysis_output("mask2R",seq,logmask,n/2,1,0,0); } #endif floor_posts[i][PACKETBLOBS-1]= floor1_fit(vb,b->flr[info->floorsubmap[submap]], logmdct, logmask); /* lower rate by way of higher noise curve */ _vp_offset_and_mix(psy_look, noise, tone, 0, logmask, mdct, logmdct); #if 0 if(vi->channels==2) if(i==0) _analysis_output("mask0L",seq,logmask,n/2,1,0,0); else _analysis_output("mask0R",seq,logmask,n/2,1,0,0); #endif floor_posts[i][0]= floor1_fit(vb,b->flr[info->floorsubmap[submap]], logmdct, logmask); /* we also interpolate a range of intermediate curves for intermediate rates */ for(k=1;k<PACKETBLOBS/2;k++) floor_posts[i][k]= floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]], floor_posts[i][0], floor_posts[i][PACKETBLOBS/2], k*65536/(PACKETBLOBS/2)); for(k=PACKETBLOBS/2+1;k<PACKETBLOBS-1;k++) floor_posts[i][k]= floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]], floor_posts[i][PACKETBLOBS/2], floor_posts[i][PACKETBLOBS-1], (k-PACKETBLOBS/2)*65536/(PACKETBLOBS/2)); } } } vbi->ampmax=global_ampmax; /* the next phases are performed once for vbr-only and PACKETBLOB times for bitrate managed modes. 1) encode actual mode being used 2) encode the floor for each channel, compute coded mask curve/res 3) normalize and couple. 4) encode residue 5) save packet bytes to the packetblob vector */ /* iterate over the many masking curve fits we've created */ { float **res_bundle=alloca(sizeof(*res_bundle)*vi->channels); float **couple_bundle=alloca(sizeof(*couple_bundle)*vi->channels); int *zerobundle=alloca(sizeof(*zerobundle)*vi->channels); int **sortindex=alloca(sizeof(*sortindex)*vi->channels); float **mag_memo; int **mag_sort; if(info->coupling_steps){ mag_memo=_vp_quantize_couple_memo(vb, &ci->psy_g_param, psy_look, info, gmdct); mag_sort=_vp_quantize_couple_sort(vb, psy_look, info, mag_memo); hf_reduction(&ci->psy_g_param, psy_look, info, mag_memo); } memset(sortindex,0,sizeof(*sortindex)*vi->channels); if(psy_look->vi->normal_channel_p){ for(i=0;i<vi->channels;i++){ float *mdct =gmdct[i]; sortindex[i]=alloca(sizeof(**sortindex)*n/2); _vp_noise_normalize_sort(psy_look,mdct,sortindex[i]); } } for(k=(vorbis_bitrate_managed(vb)?0:PACKETBLOBS/2); k<=(vorbis_bitrate_managed(vb)?PACKETBLOBS-1:PACKETBLOBS/2); k++){ oggpack_buffer *opb=vbi->packetblob[k]; /* start out our new packet blob with packet type and mode */ /* Encode the packet type */ oggpack_write(opb,0,1); /* Encode the modenumber */ /* Encode frame mode, pre,post windowsize, then dispatch */ oggpack_write(opb,modenumber,b->modebits); if(vb->W){ oggpack_write(opb,vb->lW,1); oggpack_write(opb,vb->nW,1); } /* encode floor, compute masking curve, sep out residue */ for(i=0;i<vi->channels;i++){ int submap=info->chmuxlist[i]; float *mdct =gmdct[i]; float *res =vb->pcm[i]; int *ilogmask=ilogmaskch[i]= _vorbis_block_alloc(vb,n/2*sizeof(**gmdct)); nonzero[i]=floor1_encode(opb,vb,b->flr[info->floorsubmap[submap]], floor_posts[i][k], ilogmask); #if 0 { char buf[80]; sprintf(buf,"maskI%c%d",i?'R':'L',k); float work[n/2]; for(j=0;j<n/2;j++) work[j]=FLOOR1_fromdB_LOOKUP[ilogmask[j]]; _analysis_output(buf,seq,work,n/2,1,1,0); } #endif _vp_remove_floor(psy_look, mdct, ilogmask, res, ci->psy_g_param.sliding_lowpass[vb->W][k]); _vp_noise_normalize(psy_look,res,res+n/2,sortindex[i]); #if 0 { char buf[80]; float work[n/2]; for(j=0;j<n/2;j++) work[j]=FLOOR1_fromdB_LOOKUP[ilogmask[j]]*(res+n/2)[j]; sprintf(buf,"resI%c%d",i?'R':'L',k); _analysis_output(buf,seq,work,n/2,1,1,0); } #endif } /* our iteration is now based on masking curve, not prequant and coupling. Only one prequant/coupling step */ /* quantize/couple */ /* incomplete implementation that assumes the tree is all depth one, or no tree at all */ if(info->coupling_steps){ _vp_couple(k, &ci->psy_g_param, psy_look, info, vb->pcm, mag_memo, mag_sort, ilogmaskch, nonzero, ci->psy_g_param.sliding_lowpass[vb->W][k]); } /* classify and encode by submap */ for(i=0;i<info->submaps;i++){ int ch_in_bundle=0; long **classifications; int resnum=info->residuesubmap[i]; for(j=0;j<vi->channels;j++){ if(info->chmuxlist[j]==i){ zerobundle[ch_in_bundle]=0; if(nonzero[j])zerobundle[ch_in_bundle]=1; res_bundle[ch_in_bundle]=vb->pcm[j]; couple_bundle[ch_in_bundle++]=vb->pcm[j]+n/2; } } classifications=_residue_P[ci->residue_type[resnum]]-> class(vb,b->residue[resnum],couple_bundle,zerobundle,ch_in_bundle); _residue_P[ci->residue_type[resnum]]-> forward(opb,vb,b->residue[resnum], couple_bundle,NULL,zerobundle,ch_in_bundle,classifications); } /* ok, done encoding. Next protopacket. */ } } #if 0 seq++; total+=ci->blocksizes[vb->W]/4+ci->blocksizes[vb->nW]/4; #endif return(0); }
static void *floor1_inverse1(vorbis_block *vb,vorbis_look_floor *in){ vorbis_look_floor1 *look=(vorbis_look_floor1 *)in; vorbis_info_floor1 *info=look->vi; codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup; int i,j,k; codebook *books=ci->fullbooks; /* unpack wrapped/predicted values from stream */ if(oggpack_read(&vb->opb,1)==1){ int *fit_value=(int *)_vorbis_block_alloc(vb,(look->posts)*sizeof(*fit_value)); fit_value[0]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); fit_value[1]=oggpack_read(&vb->opb,ilog(look->quant_q-1)); /* partition by partition */ /* partition by partition */ for(i=0,j=2;i<info->partitions;i++){ int classv=info->partitionclass[i]; int cdim=info->class_dim[classv]; int csubbits=info->class_subs[classv]; int csub=1<<csubbits; int cval=0; /* decode the partition's first stage cascade value */ if(csubbits){ cval=vorbis_book_decode(books+info->class_book[classv],&vb->opb); if(cval==-1)goto eop; } for(k=0;k<cdim;k++){ int book=info->class_subbook[classv][cval&(csub-1)]; cval>>=csubbits; if(book>=0){ if((fit_value[j+k]=vorbis_book_decode(books+book,&vb->opb))==-1) goto eop; }else{ fit_value[j+k]=0; } } j+=cdim; } /* unwrap positive values and reconsitute via linear interpolation */ for(i=2;i<look->posts;i++){ int predicted=render_point(info->postlist[look->loneighbor[i-2]], info->postlist[look->hineighbor[i-2]], fit_value[look->loneighbor[i-2]], fit_value[look->hineighbor[i-2]], info->postlist[i]); int hiroom=look->quant_q-predicted; int loroom=predicted; int room=(hiroom<loroom?hiroom:loroom)<<1; int val=fit_value[i]; if(val){ if(val>=room){ if(hiroom>loroom){ val = val-loroom; }else{ val = -1-(val-hiroom); } }else{ if(val&1){ val= -((val+1)>>1); }else{ val>>=1; } } fit_value[i]=val+predicted; fit_value[look->loneighbor[i-2]]&=0x7fff; fit_value[look->hineighbor[i-2]]&=0x7fff; }else{
int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){ vorbis_dsp_state *vd= vb ? vb->vd : 0; private_state *b= vd ? vd->backend_state : 0; vorbis_info *vi= vd ? vd->vi : 0; codec_setup_info *ci= vi ? vi->codec_setup : 0; oggpack_buffer *opb=vb ? &vb->opb : 0; int type,mode,i; if (!vd || !b || !vi || !ci || !opb) { return OV_EBADPACKET; } /* first things first. Make sure decode is ready */ _vorbis_block_ripcord(vb); oggpack_readinit(opb,op->packet,op->bytes); /* Check the packet type */ if(oggpack_read(opb,1)!=0){ /* Oops. This is not an audio data packet */ return(OV_ENOTAUDIO); } /* read our mode and pre/post windowsize */ mode=oggpack_read(opb,b->modebits); if(mode==-1){ return(OV_EBADPACKET); } vb->mode=mode; if(!ci->mode_param[mode]){ return(OV_EBADPACKET); } vb->W=ci->mode_param[mode]->blockflag; if(vb->W){ /* this doesn;t get mapped through mode selection as it's used only for window selection */ vb->lW=oggpack_read(opb,1); vb->nW=oggpack_read(opb,1); if(vb->nW==-1){ return(OV_EBADPACKET); } }else{ vb->lW=0; vb->nW=0; } /* more setup */ vb->granulepos=op->granulepos; vb->sequence=op->packetno; vb->eofflag=op->e_o_s; /* alloc pcm passback storage */ vb->pcmend=ci->blocksizes[vb->W]; vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels); for(i=0;i<vi->channels;i++) vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i])); /* unpack_header enforces range checking */ type=ci->map_type[ci->mode_param[mode]->mapping]; return(_mapping_P[type]->inverse(vb,ci->map_param[ci->mode_param[mode]-> mapping])); }
void bitbuf_init(vorbis_bitbuffer *vbb,vorbis_block *vb){ memset(vbb,0,sizeof(vorbis_bitbuffer)); vbb->vb=vb; vbb->first=vbb->last=_vorbis_block_alloc(vb,sizeof(vorbis_bitbuffer_chain)); vbb->first->next=0; /* overengineering */ }
static int mapping0_forward(vorbis_block *vb,vorbis_look_mapping *l){ vorbis_dsp_state *vd=vb->vd; vorbis_info *vi=vd->vi; codec_setup_info *ci=vi->codec_setup; backend_lookup_state *b=vb->vd->backend_state; vorbis_look_mapping0 *look=(vorbis_look_mapping0 *)l; vorbis_info_mapping0 *info=look->map; vorbis_info_mode *mode=look->mode; vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal; int n=vb->pcmend; int i,j; float *window=b->window[vb->W][vb->lW][vb->nW][mode->windowtype]; int *nonzero=alloca(sizeof(int)*vi->channels); float *work=_vorbis_block_alloc(vb,n*sizeof(float)); float global_ampmax=vbi->ampmax; float *local_ampmax=alloca(sizeof(float)*vi->channels); int blocktype; /* we differentiate between short and long block types to help the masking engine; the window shapes also matter. impulse block (a short block in which an impulse occurs) padding block (a short block that pads between a transitional long block and an impulse block, or vice versa) transition block (the wqeird one; a long block with the transition window; affects bass/midrange response and that must be accounted for in masking) long block (run of the mill long block) */ if(vb->W){ if(!vb->lW || !vb->nW) blocktype=BLOCKTYPE_TRANSITION; else blocktype=BLOCKTYPE_LONG; }else{ /* right now we're missing the infrastructure to distingush the two short types */ blocktype=BLOCKTYPE_IMPULSE; } for(i=0;i<vi->channels;i++){ float scale=4.f/n; /* the following makes things clearer to *me* anyway */ float *pcm =vb->pcm[i]; float *fft =work; float *logfft =pcm+n/2; /*float *res =pcm; float *mdct =pcm; float *codedflr=pcm+n/2; float *logmax =work; float *logmask =work+n/2;*/ /* window the PCM data */ for(j=0;j<n;j++) fft[j]=pcm[j]*=window[j]; /* transform the PCM data */ /* only MDCT right now.... */ mdct_forward(b->transform[vb->W][0],pcm,pcm); /* FFT yields more accurate tonal estimation (not phase sensitive) */ drft_forward(&look->fft_look,fft); fft[0]*=scale; logfft[0]=todB(fft); local_ampmax[i]=logfft[0]; for(j=1;j<n-1;j+=2){ float temp=scale*FAST_HYPOT(fft[j],fft[j+1]); temp=logfft[(j+1)>>1]=todB(&temp); if(temp>local_ampmax[i])local_ampmax[i]=temp; } if(local_ampmax[i]>global_ampmax)global_ampmax=local_ampmax[i]; _analysis_output("fft",seq+i,logfft,n/2,1,0); } for(i=0;i<vi->channels;i++){ int submap=info->chmuxlist[i]; /* the following makes things clearer to *me* anyway */ float *mdct =vb->pcm[i]; float *res =mdct; float *codedflr=mdct+n/2; float *logfft =mdct+n/2; float *logmdct =work; float *logmax =mdct+n/2; float *logmask =work+n/2; for(j=0;j<n/2;j++) logmdct[j]=todB(mdct+j); _analysis_output("mdct",seq+i,logmdct,n/2,1,0); /* perform psychoacoustics; do masking */ _vp_compute_mask(look->psy_look[blocktype], b->psy_g_look, i, logfft, /* -> logmax */ logmdct, logmask, global_ampmax, local_ampmax[i], ci->blocksizes[vb->lW]/2); _analysis_output("mask",seq+i,logmask,n/2,1,0); /* perform floor encoding */ nonzero[i]=look->floor_func[submap]-> forward(vb,look->floor_look[submap], mdct, logmdct, logmask, logmax, codedflr); _analysis_output("mdct2",seq+i,mdct,n/2,1,1); _vp_remove_floor(look->psy_look[blocktype], b->psy_g_look, logmdct, mdct, codedflr, res, local_ampmax[i]); /*for(j=0;j<n/2;j++) if(fabs(res[j])>1200){ analysis_noisy=1; fprintf(stderr,"%ld ",seq+i); }*/ _analysis_output("res",seq+i,res,n/2,1,0); _analysis_output("codedflr",seq+i,codedflr,n/2,1,1); } vbi->ampmax=global_ampmax; /* partition based prequantization and channel coupling */ /* Steps in prequant and coupling: down-couple/down-quantize from perfect residue -> quantized vector classify by this first quantized vector do{ encode quantized vector; add encoded values to 'so-far' vector more? [not yet at bitrate/not yet at target] yes{ down-couple/down-quantize from perfect-'so-far' -> quantized vector; when subtracting coupling, account for +/- out-of-phase component }no{ break } } done. quantization in each iteration is done (after circular normalization in coupling) using a by-iteration quantization granule value. */ { float **pcm=vb->pcm; float **quantized=alloca(sizeof(float*)*vi->channels); float **sofar=alloca(sizeof(float*)*vi->channels); long ***classifications=alloca(sizeof(long**)*info->submaps); float ***pcmbundle=alloca(sizeof(float **)*info->submaps); float ***sobundle=alloca(sizeof(float **)*info->submaps); int **zerobundle=alloca(sizeof(int *)*info->submaps); int *chbundle=alloca(sizeof(int)*info->submaps); int chcounter=0; /* play a little loose with this abstraction */ int quant_passes=look->psy_look[blocktype]->vi->coupling_passes; int stopflag=0; for(i=0;i<vi->channels;i++){ quantized[i]=pcm[i]+n/2; sofar[i]=_vorbis_block_alloc(vb,n/2*sizeof(float)); memset(sofar[i],0,sizeof(float)*n/2); } pcmbundle[0]=alloca(sizeof(float *)*vi->channels); sobundle[0]=alloca(sizeof(float *)*vi->channels); zerobundle[0]=alloca(sizeof(int)*vi->channels); /* initial down-quantized coupling */ if(info->coupling_steps==0){ /* this assumes all or nothing coupling right now. it should pass through any channels left uncoupled, but it doesn't do that now */ for(i=0;i<vi->channels;i++){ float *lpcm=pcm[i]; float *lqua=quantized[i]; for(j=0;j<n/2;j++) lqua[j]=lpcm[j]; } }else{ _vp_quantize_couple(look->psy_look[blocktype], info, pcm, sofar, quantized, nonzero, 0); } for(i=0;i<vi->channels;i++) _analysis_output("quant",seq+i,quantized[i],n/2,1,0); /* classify, by submap */ for(i=0;i<info->submaps;i++){ int ch_in_bundle=0; pcmbundle[i]=pcmbundle[0]+chcounter; sobundle[i]=sobundle[0]+chcounter; zerobundle[i]=zerobundle[0]+chcounter; for(j=0;j<vi->channels;j++){ if(info->chmuxlist[j]==i){ if(nonzero[j]) zerobundle[i][ch_in_bundle]=1; else zerobundle[i][ch_in_bundle]=0; pcmbundle[i][ch_in_bundle]=quantized[j]; sobundle[i][ch_in_bundle++]=sofar[j]; } } chbundle[i]=ch_in_bundle; chcounter+=ch_in_bundle; classifications[i]=look->residue_func[i]-> class(vb,look->residue_look[i],pcmbundle[i],zerobundle[i],chbundle[i]); } /* actual encoding loop */ for(i=0;!stopflag;){ /* perform residue encoding of this pass's quantized residue vector, according residue mapping */ for(j=0;j<info->submaps;j++) look->residue_func[j]-> forward(vb,look->residue_look[j], pcmbundle[j],sobundle[j],zerobundle[j],chbundle[j], i,classifications[j]); i++; /* bitrate management decision hook; the following if() is where we tell progressive encoding to halt, right now it just avoids falling off the edge */ if(i>=quant_passes /* || yadda yadda */)stopflag=1; if(!stopflag){ /* down-couple/down-quantize from perfect-'so-far' -> new quantized vector */ if(info->coupling_steps==0){ /* this assumes all or nothing coupling right now. it should pass through any channels left uncoupled, but it doesn't do that now */ for(i=0;i<vi->channels;i++){ float *lpcm=pcm[i]; float *lsof=sofar[i]; float *lqua=quantized[i]; for(j=0;j<n/2;j++) lqua[j]=lpcm[j]-lsof[j]; } }else{ _vp_quantize_couple(look->psy_look[blocktype], info, pcm, sofar, quantized, nonzero, i); } } /* steady as she goes */ } seq+=vi->channels; } look->lastframe=vb->sequence; return(0); }