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

📄 vorbisfile.c

📁 OGG文件格式音频数解压缩SDK.现在OGG文件格式在一些游戏开发中使用的比较多.
💻 C
📖 第 1 页 / 共 4 页
字号:
                   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 */

ogg_int32_t 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;
    ogg_int32_t 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;
           
            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 */

        ogg_int32_t channels=ov_info(vf,-1)->channels;
        ogg_int32_t bytespersample=word * channels;
        vorbis_fpu_control fpu = 0;

        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++) 
                            {
#if R5900
                                val=vorbis_ftoipcm(src[j]*32768.f);
#else
                                val=vorbis_ftoi(src[j]*32768.f);
                                if(val>32767)val=32767;
                                else if(val<-32768)val=-32768;
#endif
                                *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 */



ogg_int32_t 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;
      ogg_int32_t 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);

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.0f-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>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;

  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);
  
  lappcm=alloca(sizeof(*lappcm)*vi1->channels);
  n1=vorbis_info_blocksize(vi1,0)/2;
  n2=vorbis_info_blocksize(vi2,0)/2;
  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);

  /* 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;
  int i,ret;

  if(vf->ready_state<OPENED)return(OV_EINVAL);
  ret=_ov_initset(vf);
  if(ret)return(ret);
  vi=ov_info(vf,-1);
  
  ch1=vi->channels;
  n1=vorbis_info_blocksize(vi,0)/2;
  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)/2;
  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,float pos,
			   int (*localseek)(OggVorbis_File *,float)){
  vorbis_info *vi;
  float **lappcm;
  float **pcm;
  float *w1,*w2;
  int n1,n2,ch1,ch2;
  int i,ret;

  if(vf->ready_state<OPENED)return(OV_EINVAL);
  ret=_ov_initset(vf);
  if(ret)return(ret);
  vi=ov_info(vf,-1);
  
  ch1=vi->channels;
  n1=vorbis_info_blocksize(vi,0)/2;
  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)/2;
  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,float pos){
  return _ov_d_seek_lap(vf,pos,ov_time_seek);
}

int ov_time_seek_page_lap(OggVorbis_File *vf,float pos){
  return _ov_d_seek_lap(vf,pos,ov_time_seek_page);
}

⌨️ 快捷键说明

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