+/* intended for use with a specific vorbisfile feature; we want access
+ to the [usually synthetic/postextrapolated] buffer and lapping at
+ the end of a decode cycle, specifically, a half-short-block worth.
+ This funtion works like pcmout above, except it will also expose
+ 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)return 0;
+
+ /* our returned data ends at pcm_returned; because the synthesis pcm
+ buffer is a two-fragment ring, that means our data block may be
+ fragmented by buffering, wrapping or a short block not filling
+ out a buffer. To simplify things, we unfragment if it's at all
+ possibly needed. Otherwise, we'd need to call lapout more than
+ once as well as hold additional dsp state. Opt for
+ 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;
+ }
+ }
+
+ v->pcm_current-=n1;
+ v->pcm_returned-=n1;
+ v->centerW=0;
+ }
+
+ /* solidify buffer into contiguous space */
+ if((v->lW^v->W)==1){
+ /* long/short or short/long */
+ for(j=0;j<vi->channels;j++){
+ float *s=v->pcm[j];
+ float *d=v->pcm[j]+(n1-n0)/2;
+ for(i=(n1+n0)/2-1;i>=0;--i)
+ d[i]=s[i];
+ }
+ v->pcm_returned+=(n1-n0)/2;
+ v->pcm_current+=(n1-n0)/2;
+ }else{
+ if(v->lW==0){
+ /* short/short */
+ for(j=0;j<vi->channels;j++){
+ float *s=v->pcm[j];
+ float *d=v->pcm[j]+n1-n0;
+ for(i=n0-1;i>=0;--i)
+ d[i]=s[i];
+ }
+ v->pcm_returned+=n1-n0;
+ v->pcm_current+=n1-n0;
+ }
+ }
+
+ if(pcm){
+ int i;
+ for(i=0;i<vi->channels;i++)
+ v->pcmret[i]=v->pcm[i]+v->pcm_returned;
+ *pcm=v->pcmret;
+ }
+
+ return(n1+n-v->pcm_returned);
+
+}
+
+float *vorbis_window(vorbis_dsp_state *v,int W){
+ vorbis_info *vi=v->vi;
+ codec_setup_info *ci=vi->codec_setup;
+ int hs=ci->halfrate_flag;
+ private_state *b=v->backend_state;
+
+ if(b->window[W]-1<0)return NULL;
+ return _vorbis_window_get(b->window[W]-hs);
+}
+