/* Analysis side code, but directly related to blocking. Thus it's hereandnotinanalysis.c(whichisforanalysistransformsonly).
The init is here because some of it is shared */
staticint _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){ int i;
codec_setup_info *ci=vi->codec_setup;
private_state *b=NULL; int hs;
/* Vorbis I uses only window type 0 */ /* note that the correct computation below is technically: b->window[0]=ov_ilog(ci->blocksizes[0]-1)-6; b->window[1]=ov_ilog(ci->blocksizes[1]-1)-6; butsinceblocksizesarealwayspowersoftwo, thebelowisequivalent.
*/
b->window[0]=ov_ilog(ci->blocksizes[0])-7;
b->window[1]=ov_ilog(ci->blocksizes[1])-7;
if(encp){ /* encode/decode differ here */
/* analysis always needs an fft */
drft_init(&b->fft_look[0],ci->blocksizes[0]);
drft_init(&b->fft_look[1],ci->blocksizes[1]);
/* finish the codebooks */ if(!ci->fullbooks){
ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); for(i=0;i<ci->books;i++)
vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]);
}
v->analysisp=1;
}else{ /* finish the codebooks */ if(!ci->fullbooks){
ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks)); for(i=0;i<ci->books;i++){ if(ci->book_param[i]==NULL) goto abort_books; if(vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i])) goto abort_books; /* decode codebooks are now standalone after init */
vorbis_staticbook_destroy(ci->book_param[i]);
ci->book_param[i]=NULL;
}
}
}
/* initialize the storage vectors. blocksize[1] is small for encode,
but the correct size for decode */
v->pcm_storage=ci->blocksizes[1];
v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm));
v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret));
{ int i; for(i=0;i<vi->channels;i++)
v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
}
/* all 1 (large block) or 0 (small block) */ /* explicitly set for the sake of clarity */
v->lW=0; /* previous window size */
v->W=0; /* current window size */
/* all vector indexes */
v->centerW=ci->blocksizes[1]/2;
v->pcm_current=v->centerW;
/* initialize all the backend lookups */
b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr));
b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue));
/* arbitrary settings and spec-mandated numbers get filled in here */ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
private_state *b=NULL;
staticvoid _preextrapolate_helper(vorbis_dsp_state *v){ int i; int order=16; float *lpc=alloca(order*sizeof(*lpc)); float *work=alloca(v->pcm_current*sizeof(*work)); long j;
v->preextrapolate=1;
if(v->pcm_current-v->centerW>order*2){ /* safety */ for(i=0;i<v->vi->channels;i++){ /* need to run the extrapolation in reverse! */ for(j=0;j<v->pcm_current;j++)
work[j]=v->pcm[i][v->pcm_current-j-1];
/* prime as above */
vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order);
int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){
vorbis_info *vi=v->vi;
codec_setup_info *ci=vi->codec_setup;
if(vals<=0){ int order=32; int i; float *lpc=alloca(order*sizeof(*lpc));
/* if it wasn't done earlier (very short sample) */ if(!v->preextrapolate)
_preextrapolate_helper(v);
/* We're encoding the end of the stream. Just make sure we have
[at least] a few full blocks of zeroes at the end. */ /* actually, we don't want zeroes; that could drop a large amplitudeoffacliff,creatingspreadspectrumnoisethatwill
suck to encode. Extrapolate for the sake of cleanliness. */
for(i=0;i<vi->channels;i++){ if(v->eofflag>order*2){ /* extrapolate with LPC to fill in */ long n;
/* make a predictor filter */
n=v->eofflag; if(n>ci->blocksizes[1])n=ci->blocksizes[1];
vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order);
/* run the predictor filter */
vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order,
v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag);
}else{ /* not enough data to extrapolate (unlikely to happen due to guardingtheoverlap,butbulletproofincasethat
assumtion goes away). zeroes will do. */
memset(v->pcm[i]+v->eofflag,0,
(v->pcm_current-v->eofflag)*sizeof(*v->pcm[i]));
/* we may want to reverse extrapolate the beginning of a stream
too... in case we're beginning on a cliff! */ /* clumsy, but simple. It only runs once, so simple is good. */ if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1])
_preextrapolate_helper(v);
} return(0);
}
/* 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 thenextboundarysowecandeterminenW(thenextwindowsize)
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 bethrowingmorebitsatimpulses,andenvelopesearchhandles
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{
/* 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;
/* 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>0marksthelast'real'sampleinpcm[]
eof<0 'no more to do'; doesn't get here */
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);
}
int vorbis_synthesis_restart(vorbis_dsp_state *v){
vorbis_info *vi=v->vi;
codec_setup_info *ci; int hs;
/* Unlike in analysis, the window is only partially applied for each block.Thetimedomainenvelopeisnotyethandledatthepointof
calling (as it relies on the previous block). */
int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
vorbis_info *vi=v->vi;
codec_setup_info *ci=vi->codec_setup;
private_state *b=v->backend_state; int hs=ci->halfrate_flag; int i,j;
if((v->sequence==-1)||
(v->sequence+1 != vb->sequence)){
v->granulepos=-1; /* out of sequence; lose count */
b->sample_count=-1;
}
v->sequence=vb->sequence;
if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly
was called on block */ int n=ci->blocksizes[v->W]>>(hs+1); int n0=ci->blocksizes[0]>>(hs+1); int n1=ci->blocksizes[1]>>(hs+1);
/* v->pcm is now used like a two-stage double buffer. We don't want tohavetoconstantlyshift*or*adjustmemoryusage.Don't
accept a new block until the old is shifted out */
/* track the frame number... This is for convenience, but also makingsureourlastpacketdoesn'tendwithaddedpadding.If thelastpacketispartial,thenumberofsampleswe'llhaveto returnwillbepastthevb->granulepos.
Thisisnotfoolproof!Itwillbeconfusedifwebegin decodingatthelastpageafteraseekorhole.Inthatcase, wedon'thaveastartingpointtojudgewherethelastframe is.Forthisreason,vorbisfilewillalwaystrytomakesure
it reads the last two marked pages in proper sequence */
if(v->granulepos==-1){ if(vb->granulepos!=-1){ /* only set if we have a position to set to */
v->granulepos=vb->granulepos;
/* is this a short page? */ if(b->sample_count>v->granulepos){ /* corner case; if this is both the first and last audio page,
then spec says the end is cut, not beginning */ long extra=b->sample_count-vb->granulepos;
/* we use ogg_int64_t for granule positions because a uint64isn'tuniversallyavailable.Unfortunately, thatmeansgranposescanbe'negative'andresultin
extra being negative */ if(extra<0)
extra=0;
if(vb->eofflag){ /* trim the end */ /* no preceding granulepos; assume we started at zero (we'd
have to in a short single-page stream) */ /* granulepos could be -1 due to a seek, but that would result
in a long count, not short count */
/* Guard against corrupt/malicious frames that set EOP and abackdatedgranpos;don'trewindmoresamplesthanwe
actually have */ if(extra > (v->pcm_current - v->pcm_returned)<<hs)
extra = (v->pcm_current - v->pcm_returned)<<hs;
v->pcm_current-=extra>>hs;
}else{ /* trim the beginning */
v->pcm_returned+=extra>>hs; if(v->pcm_returned>v->pcm_current)
v->pcm_returned=v->pcm_current;
}
if(v->granulepos>vb->granulepos){ long extra=v->granulepos-vb->granulepos;
if(extra) if(vb->eofflag){ /* partial last frame. Strip the extra samples off */
/* Guard against corrupt/malicious frames that set EOP and abackdatedgranpos;don'trewindmoresamplesthanwe
actually have */ if(extra > (v->pcm_current - v->pcm_returned)<<hs)
extra = (v->pcm_current - v->pcm_returned)<<hs;
/* we use ogg_int64_t for granule positions because a uint64isn'tuniversallyavailable.Unfortunately, thatmeansgranposescanbe'negative'andresultin
extra being negative */ if(extra<0)
extra=0;
v->pcm_current-=extra>>hs;
} /* else {Shouldn't happen *unless* the bitstream is out of
spec. Either way, believe the bitstream } */
} /* else {Shouldn't happen *unless* the bitstream is out of
spec. Either way, believe the bitstream } */
v->granulepos=vb->granulepos;
}
}
/* Update, cleanup */
if(vb->eofflag)v->eofflag=1; return(0);
}
/* pcm==NULL indicates we just want the pending samples, no more */ int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){
vorbis_info *vi=v->vi;
int vorbis_synthesis_read(vorbis_dsp_state *v,int n){ if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL);
v->pcm_returned+=n; return(0);
}
/* intended for use with a specific vorbisfile feature; we want access tothe[usuallysynthetic/postextrapolated]bufferandlappingat theendofadecodecycle,specifically,ahalf-short-blockworth. Thisfuntionworkslikepcmoutabove,exceptitwillalsoexpose
this implicit buffer data not normally decoded. */ int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){
vorbis_info *vi=v->vi;
codec_setup_info *ci=vi->codec_setup; int hs=ci->halfrate_flag;
int n=ci->blocksizes[v->W]>>(hs+1); int n0=ci->blocksizes[0]>>(hs+1); int n1=ci->blocksizes[1]>>(hs+1); int i,j;
if(v->pcm_returned<0)return0;
/* our returned data ends at pcm_returned; because the synthesis pcm bufferisatwo-fragmentring,thatmeansourdatablockmaybe fragmentedbybuffering,wrappingorashortblocknotfilling outabuffer.Tosimplifythings,weunfragmentifit'satall possiblyneeded.Otherwise,we'dneedtocalllapoutmorethan onceaswellasholdadditionaldspstate.Optfor
simplicity. */
/* centerW was advanced by blockin; it would be the center of the
*next* block */ if(v->centerW==n1){ /* the data buffer wraps; swap the halves */ /* slow, sure, small */ for(j=0;j<vi->channels;j++){ float *p=v->pcm[j]; for(i=0;i<n1;i++){ float temp=p[i];
p[i]=p[i+n1];
p[i+n1]=temp;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.