⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vorbisfile.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 4 页
字号:
static int host_is_big_endian() {  ogg_int32_t pattern = 0xfeedface; /* deadbeef */  unsigned char *bytewise = (unsigned char *)&pattern;  if (bytewise[0] == 0xfe) return 1;  return 0;}/* up to this point, everything could more or less hide the multiple   logical bitstream nature of chaining from the toplevel application   if the toplevel application didn't particularly care.  However, at   the point that we actually read audio back, the multiple-section   nature must surface: Multiple bitstream sections do not necessarily   have to have the same number of channels or sampling rate.   ov_read returns the sequential logical bitstream number currently   being decoded along with the PCM data in order that the toplevel   application can take action on channel/sample rate changes.  This   number will be incremented even for streamed (non-seekable) streams   (for seekable streams, it represents the actual logical bitstream   index within the physical bitstream.  Note that the accessor   functions above are aware of this dichotomy).   input values: buffer) a buffer to hold packed PCM data for return		 length) the byte length requested to be placed into buffer		 bigendianp) should the data be packed LSB first (0) or		             MSB first (1)		 word) word size for output.  currently 1 (byte) or 		       2 (16 bit short)   return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)                   0) EOF		   n) number of bytes of PCM actually returned.  The		   below works on a packet-by-packet basis, so the		   return length is not related to the 'length' passed		   in, just guaranteed to fit.	    *section) set to the logical bitstream number */long ov_read(OggVorbis_File *vf,char *buffer,int length,		    int bigendianp,int word,int sgned,int *bitstream){  int i,j;  int host_endian = host_is_big_endian();  float **pcm;  long samples;  if(vf->ready_state<OPENED)return(OV_EINVAL);  while(1){    if(vf->ready_state==INITSET){      samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);      if(samples)break;    }    /* suck in another packet */    {      int ret=_fetch_and_process_packet(vf,NULL,1,1);      if(ret==OV_EOF)	return(0);      if(ret<=0)	return(ret);    }  }  if(samples>0){      /* yay! proceed to pack data into the byte buffer */        long channels=ov_info(vf,-1)->channels;    long bytespersample=word * channels;    vorbis_fpu_control fpu;    if(samples>length/bytespersample)samples=length/bytespersample;    if(samples <= 0)      return OV_EINVAL;        /* a tight loop to pack each size */    {      int val;      if(word==1){	int off=(sgned?0:128);	vorbis_fpu_setround(&fpu);	for(j=0;j<samples;j++)	  for(i=0;i<channels;i++){	    val=vorbis_ftoi(pcm[i][j]*128.f);	    if(val>127)val=127;	    else if(val<-128)val=-128;	    *buffer++=val+off;	  }	vorbis_fpu_restore(fpu);      }else{	int off=(sgned?0:32768);		if(host_endian==bigendianp){	  if(sgned){	    	    vorbis_fpu_setround(&fpu);	    for(i=0;i<channels;i++) { /* It's faster in this order */	      float *src=pcm[i];	      short *dest=((short *)buffer)+i;	      for(j=0;j<samples;j++) {		val=vorbis_ftoi(src[j]*32768.f);		if(val>32767)val=32767;		else if(val<-32768)val=-32768;		*dest=val;		dest+=channels;	      }	    }	    vorbis_fpu_restore(fpu);	    	  }else{	    	    vorbis_fpu_setround(&fpu);	    for(i=0;i<channels;i++) {	      float *src=pcm[i];	      short *dest=((short *)buffer)+i;	      for(j=0;j<samples;j++) {		val=vorbis_ftoi(src[j]*32768.f);		if(val>32767)val=32767;		else if(val<-32768)val=-32768;		*dest=val+off;		dest+=channels;	      }	    }	    vorbis_fpu_restore(fpu);	    	  }	}else if(bigendianp){	  	  vorbis_fpu_setround(&fpu);	  for(j=0;j<samples;j++)	    for(i=0;i<channels;i++){	      val=vorbis_ftoi(pcm[i][j]*32768.f);	      if(val>32767)val=32767;	      else if(val<-32768)val=-32768;	      val+=off;	      *buffer++=(val>>8);	      *buffer++=(val&0xff);	    }	  vorbis_fpu_restore(fpu);	  	}else{	  int val;	  vorbis_fpu_setround(&fpu);	  for(j=0;j<samples;j++)	    for(i=0;i<channels;i++){	      val=vorbis_ftoi(pcm[i][j]*32768.f);	      if(val>32767)val=32767;	      else if(val<-32768)val=-32768;	      val+=off;	      *buffer++=(val&0xff);	      *buffer++=(val>>8);	  	}	  vorbis_fpu_restore(fpu);  	  	}      }    }        vorbis_synthesis_read(&vf->vd,samples);    vf->pcm_offset+=samples;    if(bitstream)*bitstream=vf->current_link;    return(samples*bytespersample);  }else{    return(samples);  }}/* input values: pcm_channels) a float vector per channel of output		 length) the sample length being read by the app   return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)                   0) EOF		   n) number of samples of PCM actually returned.  The		   below works on a packet-by-packet basis, so the		   return length is not related to the 'length' passed		   in, just guaranteed to fit.	    *section) set to the logical bitstream number */long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,		   int *bitstream){  if(vf->ready_state<OPENED)return(OV_EINVAL);  while(1){    if(vf->ready_state==INITSET){      float **pcm;      long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);      if(samples){	if(pcm_channels)*pcm_channels=pcm;	if(samples>length)samples=length;	vorbis_synthesis_read(&vf->vd,samples);	vf->pcm_offset+=samples;	if(bitstream)*bitstream=vf->current_link;	return samples;      }    }    /* suck in another packet */    {      int ret=_fetch_and_process_packet(vf,NULL,1,1);      if(ret==OV_EOF)return(0);      if(ret<=0)return(ret);    }  }}extern float *vorbis_window(vorbis_dsp_state *v,int W);extern void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB,			     ogg_int64_t off);static void _ov_splice(float **pcm,float **lappcm,		       int n1, int n2,		       int ch1, int ch2,		       float *w1, float *w2){  int i,j;  float *w=w1;  int n=n1;  if(n1>n2){    n=n2;    w=w2;  }  /* splice */  for(j=0;j<ch1 && j<ch2;j++){    float *s=lappcm[j];    float *d=pcm[j];    for(i=0;i<n;i++){      float wd=w[i]*w[i];      float ws=1.-wd;      d[i]=d[i]*wd + s[i]*ws;    }  }  /* window from zero */  for(;j<ch2;j++){    float *d=pcm[j];    for(i=0;i<n;i++){      float wd=w[i]*w[i];      d[i]=d[i]*wd;    }  }}		/* make sure vf is INITSET */static int _ov_initset(OggVorbis_File *vf){  while(1){    if(vf->ready_state==INITSET)break;    /* suck in another packet */    {      int ret=_fetch_and_process_packet(vf,NULL,1,0);      if(ret<0 && ret!=OV_HOLE)return(ret);    }  }  return 0;}/* make sure vf is INITSET and that we have a primed buffer; if   we're crosslapping at a stream section boundary, this also makes   sure we're sanity checking against the right stream information */static int _ov_initprime(OggVorbis_File *vf){  vorbis_dsp_state *vd=&vf->vd;  while(1){    if(vf->ready_state==INITSET)      if(vorbis_synthesis_pcmout(vd,NULL))break;        /* suck in another packet */    {      int ret=_fetch_and_process_packet(vf,NULL,1,0);      if(ret<0 && ret!=OV_HOLE)return(ret);    }  }    return 0;}/* grab enough data for lapping from vf; this may be in the form of   unreturned, already-decoded pcm, remaining PCM we will need to   decode, or synthetic postextrapolation from last packets. */static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd,		       float **lappcm,int lapsize){  int lapcount=0,i;  float **pcm;  /* try first to decode the lapping data */  while(lapcount<lapsize){    int samples=vorbis_synthesis_pcmout(vd,&pcm);    if(samples){      if(samples>lapsize-lapcount)samples=lapsize-lapcount;      for(i=0;i<vi->channels;i++)	memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);      lapcount+=samples;      vorbis_synthesis_read(vd,samples);    }else{    /* suck in another packet */      int ret=_fetch_and_process_packet(vf,NULL,1,0); /* do *not* span */      if(ret==OV_EOF)break;    }  }  if(lapcount<lapsize){    /* failed to get lapping data from normal decode; pry it from the       postextrapolation buffering, or the second half of the MDCT       from the last packet */    int samples=vorbis_synthesis_lapout(&vf->vd,&pcm);    if(samples==0){      for(i=0;i<vi->channels;i++)	memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount);      lapcount=lapsize;    }else{      if(samples>lapsize-lapcount)samples=lapsize-lapcount;      for(i=0;i<vi->channels;i++)	memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);      lapcount+=samples;    }  }}/* this sets up crosslapping of a sample by using trailing data from   sample 1 and lapping it into the windowing buffer of sample 2 */int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){  vorbis_info *vi1,*vi2;  float **lappcm;  float **pcm;  float *w1,*w2;  int n1,n2,i,ret,hs1,hs2;  if(vf1==vf2)return(0); /* degenerate case */  if(vf1->ready_state<OPENED)return(OV_EINVAL);  if(vf2->ready_state<OPENED)return(OV_EINVAL);  /* the relevant overlap buffers must be pre-checked and pre-primed     before looking at settings in the event that priming would cross     a bitstream boundary.  So, do it now */  ret=_ov_initset(vf1);  if(ret)return(ret);  ret=_ov_initprime(vf2);  if(ret)return(ret);  vi1=ov_info(vf1,-1);  vi2=ov_info(vf2,-1);  hs1=ov_halfrate_p(vf1);  hs2=ov_halfrate_p(vf2);  lappcm=alloca(sizeof(*lappcm)*vi1->channels);  n1=vorbis_info_blocksize(vi1,0)>>(1+hs1);  n2=vorbis_info_blocksize(vi2,0)>>(1+hs2);  w1=vorbis_window(&vf1->vd,0);  w2=vorbis_window(&vf2->vd,0);  for(i=0;i<vi1->channels;i++)    lappcm[i]=alloca(sizeof(**lappcm)*n1);  _ov_getlap(vf1,vi1,&vf1->vd,lappcm,n1);  /* have a lapping buffer from vf1; now to splice it into the lapping     buffer of vf2 */  /* consolidate and expose the buffer. */  vorbis_synthesis_lapout(&vf2->vd,&pcm);  _analysis_output_always("pcmL",0,pcm[0],n1*2,0,0,0);  _analysis_output_always("pcmR",0,pcm[1],n1*2,0,0,0);  /* splice */  _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2);    /* done */  return(0);}static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,			   int (*localseek)(OggVorbis_File *,ogg_int64_t)){  vorbis_info *vi;  float **lappcm;  float **pcm;  float *w1,*w2;  int n1,n2,ch1,ch2,hs;  int i,ret;  if(vf->ready_state<OPENED)return(OV_EINVAL);  ret=_ov_initset(vf);  if(ret)return(ret);  vi=ov_info(vf,-1);  hs=ov_halfrate_p(vf);    ch1=vi->channels;  n1=vorbis_info_blocksize(vi,0)>>(1+hs);  w1=vorbis_window(&vf->vd,0);  /* window arrays from libvorbis are				   persistent; even if the decode state				   from this link gets dumped, this				   window array continues to exist */  lappcm=alloca(sizeof(*lappcm)*ch1);  for(i=0;i<ch1;i++)    lappcm[i]=alloca(sizeof(**lappcm)*n1);  _ov_getlap(vf,vi,&vf->vd,lappcm,n1);  /* have lapping data; seek and prime the buffer */  ret=localseek(vf,pos);  if(ret)return ret;  ret=_ov_initprime(vf);  if(ret)return(ret); /* Guard against cross-link changes; they're perfectly legal */  vi=ov_info(vf,-1);  ch2=vi->channels;  n2=vorbis_info_blocksize(vi,0)>>(1+hs);  w2=vorbis_window(&vf->vd,0);  /* consolidate and expose the buffer. */  vorbis_synthesis_lapout(&vf->vd,&pcm);  /* splice */  _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);  /* done */  return(0);}int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){  return _ov_64_seek_lap(vf,pos,ov_raw_seek);}int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){  return _ov_64_seek_lap(vf,pos,ov_pcm_seek);}int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos){  return _ov_64_seek_lap(vf,pos,ov_pcm_seek_page);}static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,			   int (*localseek)(OggVorbis_File *,double)){  vorbis_info *vi;  float **lappcm;  float **pcm;  float *w1,*w2;  int n1,n2,ch1,ch2,hs;  int i,ret;  if(vf->ready_state<OPENED)return(OV_EINVAL);  ret=_ov_initset(vf);  if(ret)return(ret);  vi=ov_info(vf,-1);  hs=ov_halfrate_p(vf);  ch1=vi->channels;  n1=vorbis_info_blocksize(vi,0)>>(1+hs);  w1=vorbis_window(&vf->vd,0);  /* window arrays from libvorbis are				   persistent; even if the decode state				   from this link gets dumped, this				   window array continues to exist */  lappcm=alloca(sizeof(*lappcm)*ch1);  for(i=0;i<ch1;i++)    lappcm[i]=alloca(sizeof(**lappcm)*n1);  _ov_getlap(vf,vi,&vf->vd,lappcm,n1);  /* have lapping data; seek and prime the buffer */  ret=localseek(vf,pos);  if(ret)return ret;  ret=_ov_initprime(vf);  if(ret)return(ret); /* Guard against cross-link changes; they're perfectly legal */  vi=ov_info(vf,-1);  ch2=vi->channels;  n2=vorbis_info_blocksize(vi,0)>>(1+hs);  w2=vorbis_window(&vf->vd,0);  /* consolidate and expose the buffer. */  vorbis_synthesis_lapout(&vf->vd,&pcm);  /* splice */  _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);  /* done */  return(0);}int ov_time_seek_lap(OggVorbis_File *vf,double pos){  return _ov_d_seek_lap(vf,pos,ov_time_seek);}int ov_time_seek_page_lap(OggVorbis_File *vf,double pos){  return _ov_d_seek_lap(vf,pos,ov_time_seek_page);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -