static int read_samples(struct ast_filestream *fs, float ***pcm)
{
	int samples_in;
	int result;
	char *buffer;
	int bytes;
	struct vorbis_desc *s = (struct vorbis_desc *)fs->_private;

	while (1) {
		samples_in = vorbis_synthesis_pcmout(&s->vd, pcm);
		if (samples_in > 0) {
			return samples_in;
		}

		/* The Vorbis decoder needs more data... */
		/* See ifOGG has any packets in the current page for the Vorbis decoder. */
		result = ogg_stream_packetout(&s->os, &s->op);
		if (result > 0) {
			/* Yes OGG had some more packets for the Vorbis decoder. */
			if (vorbis_synthesis(&s->vb, &s->op) == 0) {
				vorbis_synthesis_blockin(&s->vd, &s->vb);
			}

			continue;
		}

		if (result < 0)
			ast_log(LOG_WARNING,
					"Corrupt or missing data at this page position; continuing...\n");

		/* No more packets left in the current page... */

		if (s->eos) {
			/* No more pages left in the stream */
			return -1;
		}

		while (!s->eos) {
			/* See ifOGG has any pages in it's internal buffers */
			result = ogg_sync_pageout(&s->oy, &s->og);
			if (result > 0) {
				/* Yes, OGG has more pages in it's internal buffers,
				   add the page to the stream state */
				result = ogg_stream_pagein(&s->os, &s->og);
				if (result == 0) {
					/* Yes, got a new,valid page */
					if (ogg_page_eos(&s->og)) {
						s->eos = 1;
					}
					break;
				}
				ast_log(LOG_WARNING,
						"Invalid page in the bitstream; continuing...\n");
			}

			if (result < 0)
				ast_log(LOG_WARNING,
						"Corrupt or missing data in bitstream; continuing...\n");

			/* No, we need to read more data from the file descrptor */
			/* get a buffer from OGG to read the data into */
			buffer = ogg_sync_buffer(&s->oy, BLOCK_SIZE);
			/* read more data from the file descriptor */
			bytes = fread(buffer, 1, BLOCK_SIZE, fs->f);
			/* Tell OGG how many bytes we actually read into the buffer */
			ogg_sync_wrote(&s->oy, bytes);
			if (bytes == 0) {
				s->eos = 1;
			}
		}
	}
}
Exemple #2
0
static int
ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE* odata)
{   char *buffer ;
    int	 bytes, nn ;

    /* Call this here so it only gets called once, so no memory is leaked. */
    ogg_sync_init (&odata->osync) ;

    odata->eos = 0 ;

    /* Weird stuff happens if these aren't called. */
    ogg_stream_reset (&odata->ostream) ;
    ogg_sync_reset (&odata->osync) ;

    /*
    **	Grab some data at the head of the stream.  We want the first page
    **	(which is guaranteed to be small and only contain the Vorbis
    **	stream initial header) We need the first page to get the stream
    **	serialno.
    */

    /* Expose the buffer */
    buffer = ogg_sync_buffer (&odata->osync, 4096L) ;

    /* Grab the part of the header that has already been read. */
    memcpy (buffer, psf->header, psf->headindex) ;
    bytes = psf->headindex ;

    /* Submit a 4k block to libvorbis' Ogg layer */
    bytes += psf_fread (buffer + psf->headindex, 1, 4096 - psf->headindex, psf) ;
    ogg_sync_wrote (&odata->osync, bytes) ;

    /* Get the first page. */
    if ((nn = ogg_sync_pageout (&odata->osync, &odata->opage)) != 1)
    {
        /* Have we simply run out of data?  If so, we're done. */
        if (bytes < 4096)
            return 0 ;

        /* Error case.  Must not be Vorbis data */
        psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    /*
    **	Get the serial number and set up the rest of decode.
    **	Serialno first ; use it to set up a logical stream.
    */
    ogg_stream_clear (&odata->ostream) ;
    ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;

    if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0)
    {   /* Error ; stream version mismatch perhaps. */
        psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1)
    {   /* No page? must not be vorbis. */
        psf_log_printf (psf, "Error reading initial header packet.\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    odata->codec = ogg_page_classify (psf, &odata->opage) ;

    switch (odata->codec)
    {
    case OGG_VORBIS :
        psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
        return 0 ;

    case OGG_FLAC :
    case OGG_FLAC0 :
        psf->sf.format = SF_FORMAT_OGGFLAC ;
        return 0 ;

    case OGG_SPEEX :
        psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
        return 0 ;

    case OGG_PCM :
        psf_log_printf (psf, "Detected Ogg/PCM data. This is not supported yet.\n") ;
        return SFE_UNIMPLEMENTED ;

    default :
        break ;
    } ;

    psf_log_printf (psf, "This Ogg bitstream contains some uknown data type.\n") ;
    return SFE_UNIMPLEMENTED ;
} /* ogg_stream_classify */
Exemple #3
0
static int
ogg_read_header (SF_PRIVATE *psf, int log_data)
{
    OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
    VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
    char *buffer ;
    int	 bytes ;
    int i, nn ;

    odata->eos = 0 ;

    /* Weird stuff happens if these aren't called. */
    ogg_stream_reset (&odata->os) ;
    ogg_sync_reset (&odata->oy) ;

    /*
    **	Grab some data at the head of the stream.  We want the first page
    **	(which is guaranteed to be small and only contain the Vorbis
    **	stream initial header) We need the first page to get the stream
    **	serialno.
    */

    /* Expose the buffer */
    buffer = ogg_sync_buffer (&odata->oy, 4096L) ;

    /* Grab the part of the header that has already been read. */
    memcpy (buffer, psf->header, psf->headindex) ;
    bytes = psf->headindex ;

    /* Submit a 4k block to libvorbis' Ogg layer */
    bytes += psf_fread (buffer + psf->headindex, 1, 4096 - psf->headindex, psf) ;
    ogg_sync_wrote (&odata->oy, bytes) ;

    /* Get the first page. */
    if ((nn = ogg_sync_pageout (&odata->oy, &odata->og)) != 1)
    {
        /* Have we simply run out of data?  If so, we're done. */
        if (bytes < 4096)
            return 0 ;

        /* Error case.  Must not be Vorbis data */
        psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    /*
    **	Get the serial number and set up the rest of decode.
    **	Serialno first ; use it to set up a logical stream.
    */
    ogg_stream_clear (&odata->os) ;
    ogg_stream_init (&odata->os, ogg_page_serialno (&odata->og)) ;

    /*
    **	This function (ogg_read_header) gets called multiple times, so the OGG
    **	and vorbis structs have to be cleared every time we pass through to
    **	prevent memory leaks.
    */
    vorbis_block_clear (&vdata->vb) ;
    vorbis_dsp_clear (&vdata->vd) ;
    vorbis_comment_clear (&vdata->vc) ;
    vorbis_info_clear (&vdata->vi) ;

    /*
    **	Extract the initial header from the first page and verify that the
    **	Ogg bitstream is in fact Vorbis data.
    **
    **	I handle the initial header first instead of just having the code
    **	read all three Vorbis headers at once because reading the initial
    **	header is an easy way to identify a Vorbis bitstream and it's
    **	useful to see that functionality seperated out.
    */
    vorbis_info_init (&vdata->vi) ;
    vorbis_comment_init (&vdata->vc) ;

    if (ogg_stream_pagein (&odata->os, &odata->og) < 0)
    {   /* Error ; stream version mismatch perhaps. */
        psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    if (ogg_stream_packetout (&odata->os, &odata->op) != 1)
    {   /* No page? must not be vorbis. */
        psf_log_printf (psf, "Error reading initial header packet.\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    if (vorbis_synthesis_headerin (&vdata->vi, &vdata->vc, &odata->op) < 0)
    {   /* Error case ; not a vorbis header. */
        psf_log_printf (psf, "This Ogg bitstream does not contain Vorbis audio data.\n") ;
        return SFE_MALFORMED_FILE ;
    } ;

    /*
    **	Common Ogg metadata fields?
    **	TITLE, VERSION, ALBUM, TRACKNUMBER, ARTIST, PERFORMER, COPYRIGHT, LICENSE,
    **	ORGANIZATION, DESCRIPTION, GENRE, DATE, LOCATION, CONTACT, ISRC,
    */

    if (log_data)
    {   int k ;

        for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
        {   char *dd ;

            dd = vorbis_comment_query (&vdata->vc, vorbis_metatypes [k].name, 0) ;
            if (dd == NULL)
                continue ;
            psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
        } ;
    } ;

    /*
    **	At this point, we're sure we're Vorbis.	We've set up the logical (Ogg)
    **	bitstream decoder. Get the comment and codebook headers and set up the
    **	Vorbis decoder.
    **
    **	The next two packets in order are the comment and codebook headers.
    **	They're likely large and may span multiple pages.  Thus we reead
    **	and submit data until we get our two pacakets, watching that no
    **	pages are missing.  If a page is missing, error out ; losing a
    **	header page is the only place where missing data is fatal.
    */

    i = 0 ;			 /* Count of number of packets read */
    while (i < 2)
    {   int result = ogg_sync_pageout (&odata->oy, &odata->og) ;
        if (result == 0)
        {   /* Need more data */
            buffer = ogg_sync_buffer (&odata->oy, 4096) ;
            bytes = psf_fread (buffer, 1, 4096, psf) ;

            if (bytes == 0 && i < 2)
            {   psf_log_printf (psf, "End of file before finding all Vorbis headers!\n") ;
                return SFE_MALFORMED_FILE ;
            } ;
            nn = ogg_sync_wrote (&odata->oy, bytes) ;
        }
        else if (result == 1)
        {   /*
            **	Don't complain about missing or corrupt data yet. We'll
            **	catch it at the packet output phase.
            **
            **	We can ignore any errors here as they'll also become apparent
            **	at packetout.
            */
            nn = ogg_stream_pagein (&odata->os, &odata->og) ;
            while (i < 2)
            {   result = ogg_stream_packetout (&odata->os, &odata->op) ;
                if (result == 0)
                    break ;
                if (result < 0)
                {   /*	Uh oh ; data at some point was corrupted or missing!
                    **	We can't tolerate that in a header. Die. */
                    psf_log_printf (psf, "Corrupt secondary header.	Exiting.\n") ;
                    return SFE_MALFORMED_FILE ;
                } ;

                vorbis_synthesis_headerin (&vdata->vi, &vdata->vc, &odata->op) ;
                i++ ;
            } ;
        } ;
    } ;

    if (log_data)
    {   int printed_metadata_msg = 0 ;
        int k ;

        psf_log_printf (psf, "\nBitstream is %d channel, %D Hz\n", vdata->vi.channels, vdata->vi.rate) ;
        psf_log_printf (psf, "Encoded by: %s\n", vdata->vc.vendor) ;

        /* Throw the comments plus a few lines about the bitstream we're decoding. */
        for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
        {   char *dd ;

            dd = vorbis_comment_query (&vdata->vc, vorbis_metatypes [k].name, 0) ;
            if (dd == NULL)
                continue ;

            if (printed_metadata_msg == 0)
            {   psf_log_printf (psf, "Metadata :\n") ;
                printed_metadata_msg = 1 ;
            } ;

            psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
            psf_log_printf (psf, "  %-10s : %s\n", vorbis_metatypes [k].name, dd) ;
        } ;

        psf_log_printf (psf, "End\n") ;
    } ;

    psf->sf.samplerate	= vdata->vi.rate ;
    psf->sf.channels	= vdata->vi.channels ;
    psf->sf.format		= SF_FORMAT_OGG | SF_FORMAT_VORBIS ;

    /*	OK, got and parsed all three headers. Initialize the Vorbis
    **	packet->PCM decoder.
    **	Central decode state. */
    vorbis_synthesis_init (&vdata->vd, &vdata->vi) ;

    /*	Local state for most of the decode so multiple block decodes can
    **	proceed in parallel. We could init multiple vorbis_block structures
    **	for vd here. */
    vorbis_block_init (&vdata->vd, &vdata->vb) ;

    vdata->loc = 0 ;

    return 0 ;
} /* ogg_read_header */
Exemple #4
0
// the main page reading hook (stream friendly)
ssize_t
OggReader::ReadPage(bool first_page)
{
//	TRACE("OggReader::ReadPage\n");
	int read_size = (first_page ? 4096 : 4*B_PAGE_SIZE);
	BAutolock autolock(fSyncLock);
	ogg_page page;
retry:
	int result = ogg_sync_pageout(&fSync, &page); // first read leftovers
	while (result == 0) {
		char * buffer = ogg_sync_buffer(&fSync, read_size);
		ssize_t bytes = Source()->Read(buffer, read_size);
		if (bytes == 0) {
			TRACE("OggReader::GetPage: Read: no data\n");
			return B_LAST_BUFFER_ERROR;
		}
		if (bytes < 0) {
			TRACE("OggReader::GetPage: Read: error\n");
			return bytes;
		}
		if (ogg_sync_wrote(&fSync, bytes) != 0) {
			TRACE("OggReader::GetPage: ogg_sync_wrote failed?: error\n");
			return B_ERROR;
		}
		result = ogg_sync_pageout(&fSync, &page);
		if (first_page && (result != 1)) {
			TRACE("OggReader::GetPage: short first page not found: error\n");
			return B_ERROR;
		}
	}
	if (result == -1) {
		TRACE("OggReader::GetPage: ogg_sync_pageout: not synced: error\n");
		return B_ERROR;
	}
	if (ogg_page_version(&page) != 0) {
		TRACE("OggReader::GetPage: ogg_page_version: error in page encoding: error\n");
		return B_ERROR;
	}
	long serialno = ogg_page_serialno(&page);
	bool new_serialno = fTracks.find(serialno) == fTracks.end();
	if (new_serialno) {
		// this is an unknown serialno
		if (ogg_page_bos(&page) == 0) {
			TRACE("OggReader::GetPage: non-bos page with unknown serialno\n");
#ifdef STRICT_OGG
			return B_ERROR;
#else
			// silently discard non-bos packets with unknown serialno
			goto retry;
#endif
		}
#ifdef STRICT_OGG
		if (ogg_page_continued(&page) != 0) {
			TRACE("oggReader::GetPage: ogg_page_continued: continued page: not ogg\n");
			return B_ERROR;
		}
#endif //STRICT_OGG
		// this is a beginning of stream page
		ogg_stream_state stream;
		if (ogg_stream_init(&stream, serialno) != 0) {
			TRACE("oggReader::GetPage: ogg_stream_init failed?: error\n");
			return B_ERROR;
		}
		if (ogg_stream_pagein(&stream, &page) != 0) {
			TRACE("oggReader::GetPage: ogg_stream_pagein: failed: error\n");
			return B_ERROR;
		}
		ogg_packet packet;
		if (ogg_stream_packetout(&stream, &packet) != 1) {
#ifdef STRICT_OGG
			return B_ERROR;
#endif //STRICT_OGG
		}
		if (fSeekable) {
			fTracks[serialno] = OggSeekable::makeOggSeekable(fSeekable, &fSeekableLock, serialno, packet);
		} else {
			class Interface : public StreamInterface {
			private:
				OggReader * reader;
			public:
				Interface(OggReader * reader) {
					this->reader = reader;
				}
				virtual ssize_t ReadPage() {
					return reader->ReadPage();
				}
			};
			fTracks[serialno] = OggStream::makeOggStream(new Interface(this), serialno, packet);
		}
		fCookies.push_back(serialno);
	}
	// this check ensures that we only push the initial pages into OggSeekables.
	if (!fSeekable || new_serialno) {
		status_t status = fTracks[serialno]->AddPage(fPosition, page);
		if (status != B_OK) {
			return status;
		}
		fPosition += page.header_len + page.body_len;
	}
	return page.header_len + page.body_len;
}
Exemple #5
0
int main(){
  ogg_sync_state   oy; /* sync and verify incoming physical bitstream */
  ogg_stream_state os; /* take physical pages, weld into a logical
			  stream of packets */
  ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
  ogg_packet       op; /* one raw packet of data for decode */
  
  vorbis_info      vi; /* struct that stores all the static vorbis bitstream
			  settings */
  vorbis_comment   vc; /* struct that stores all the bitstream user comments */
  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
  vorbis_block     vb; /* local working space for packet->PCM decode */
  
  char *buffer;
  int  bytes;

#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
  /* Beware the evil ifdef. We avoid these where we can, but this one we 
     cannot. Don't add any more, you'll probably go to hell if you do. */
  _setmode( _fileno( stdin ), _O_BINARY );
  _setmode( _fileno( stdout ), _O_BINARY );
#endif

#if defined(macintosh) && defined(__MWERKS__)
  {
    int argc;
    char **argv;
    argc=ccommand(&argv); /* get a "command line" from the Mac user */
                     /* this also lets the user set stdin and stdout */
  }
#endif

  /********** Decode setup ************/

  ogg_sync_init(&oy); /* Now we can read pages */
  
  while(1){ /* we repeat if the bitstream is chained */
    int eos=0;
    int i;

    /* grab some data at the head of the stream.  We want the first page
       (which is guaranteed to be small and only contain the Vorbis
       stream initial header) We need the first page to get the stream
       serialno. */
	FILE * pFile = NULL;
	pFile = fopen( "D:\\data\\tree.mine\\libvorbis-1.2.0\\win32\\Debug\\Epoq-Lepidoptera.ogg", "rb" );

    /* submit a 4k block to libvorbis' Ogg layer */
    buffer=ogg_sync_buffer(&oy,4096);
    bytes=fread(buffer,1,4096,pFile);
    ogg_sync_wrote(&oy,bytes);
    
    /* Get the first page. */
    if(ogg_sync_pageout(&oy,&og)!=1){
      /* have we simply run out of data?  If so, we're done. */
      if(bytes<4096)break;
      
      /* error case.  Must not be Vorbis data */
      fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
      exit(1);
    }
  
    /* Get the serial number and set up the rest of decode. */
    /* serialno first; use it to set up a logical stream */
    ogg_stream_init(&os,ogg_page_serialno(&og));
    
    /* extract the initial header from the first page and verify that the
       Ogg bitstream is in fact Vorbis data */
    
    /* I handle the initial header first instead of just having the code
       read all three Vorbis headers at once because reading the initial
       header is an easy way to identify a Vorbis bitstream and it's
       useful to see that functionality seperated out. */
    
    vorbis_info_init(&vi);
    vorbis_comment_init(&vc);
    if(ogg_stream_pagein(&os,&og)<0){ 
      /* error; stream version mismatch perhaps */
      fprintf(stderr,"Error reading first page of Ogg bitstream data.\n");
      exit(1);
    }
    
    if(ogg_stream_packetout(&os,&op)!=1){ 
      /* no page? must not be vorbis */
      fprintf(stderr,"Error reading initial header packet.\n");
      exit(1);
    }
    
    if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){ 
      /* error case; not a vorbis header */
      fprintf(stderr,"This Ogg bitstream does not contain Vorbis "
	      "audio data.\n");
      exit(1);
    }
    
    /* At this point, we're sure we're Vorbis.  We've set up the logical
       (Ogg) bitstream decoder.  Get the comment and codebook headers and
       set up the Vorbis decoder */
    
    /* The next two packets in order are the comment and codebook headers.
       They're likely large and may span multiple pages.  Thus we reead
       and submit data until we get our two pacakets, watching that no
       pages are missing.  If a page is missing, error out; losing a
       header page is the only place where missing data is fatal. */
    
    i=0;
    while(i<2)
	{
      while(i<2)
	  {
		int result=ogg_sync_pageout(&oy,&og);
		if(result==0)
			break; /* Need more data */
		/* Don't complain about missing or corrupt data yet.  We'll
		   catch it at the packet output phase */
		if(result==1)
		{
		  ogg_stream_pagein(&os,&og); /* we can ignore any errors here
						 as they'll also become apparent
						 at packetout */
		  while(i<2)
		  {
			result=ogg_stream_packetout(&os,&op);
			if(result==0)break;
			if(result<0)
			{
			  /* Uh oh; data at some point was corrupted or missing!
			 We can't tolerate that in a header.  Die. */
			  fprintf(stderr,"Corrupt secondary header.  Exiting.\n");
			  exit(1);
			}
			vorbis_synthesis_headerin(&vi,&vc,&op);
			i++;
		  }
		}
	  
	  }
      /* no harm in not checking before adding more */
      buffer=ogg_sync_buffer(&oy,4096);
      bytes=fread(buffer,1,4096,pFile);
      if(bytes==0 && i<2)
	  {
		  fprintf(stderr,"End of file before finding all Vorbis headers!\n");
		  exit(1);
      }
      ogg_sync_wrote(&oy,bytes);
    }
    
    /* Throw the comments plus a few lines about the bitstream we're
       decoding */
    {
      char **ptr=vc.user_comments;
      while(*ptr)
	  {
		  fprintf(stderr,"%s\n",*ptr);
		  ++ptr;
      }
      fprintf(stderr,"\nBitstream is %d channel, %ldHz\n",vi.channels,vi.rate);
      fprintf(stderr,"Encoded by: %s\n\n",vc.vendor);
    }
    
    convsize=4096/vi.channels;

    /* OK, got and parsed all three headers. Initialize the Vorbis
       packet->PCM decoder. */
    vorbis_synthesis_init(&vd,&vi); /* central decode state */
    vorbis_block_init(&vd,&vb);     /* local state for most of the decode
				       so multiple block decodes can
				       proceed in parallel.  We could init
				       multiple vorbis_block structures
				       for vd here */
    
    /* The rest is just a straight decode loop until end of stream */
    while(!eos)
	{
      while(!eos)
	  {
		  int result=ogg_sync_pageout(&oy,&og);
		if(result==0)break; /* need more data */
		if(result<0)
		{ /* missing or corrupt data at this page position */
		  fprintf(stderr,"Corrupt or missing data in bitstream; "
			  "continuing...\n");
		}else
		{
		  ogg_stream_pagein(&os,&og); /* can safely ignore errors at
						 this point */
		  while(1)
		  {
			result=ogg_stream_packetout(&os,&op);

			if(result==0)break; /* need more data */
			if(result<0){ /* missing or corrupt data at this page position */
			  /* no reason to complain; already complained above */
			}else
			{
			  /* we have a packet.  Decode it */
			  float **pcm;
			  int samples;
		      
			  if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
				  vorbis_synthesis_blockin(&vd,&vb);
			  /* 
			 
			  **pcm is a multichannel float vector.  In stereo, for
			  example, pcm[0] is left, and pcm[1] is right.  samples is
			  the size of each channel.  Convert the float values
			  (-1.<=range<=1.) to whatever PCM format and write it out */
		      
			  while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0)
			  {
				int j;
				int clipflag=0;
				int bout=(samples<convsize?samples:convsize);
				
				/* convert floats to 16 bit signed ints (host order) and
				   interleave */
				for(i=0;i<vi.channels;i++)
				{
				  ogg_int16_t *ptr=convbuffer+i;
				  float  *mono=pcm[i];
				  for(j=0;j<bout;j++)
				  {
		#if 1
					int val=mono[j]*32767.f;
		#else /* optional dither */
					int val=mono[j]*32767.f+drand48()-0.5f;
		#endif
					/* might as well guard against clipping */
					if(val>32767)
					{
					  val=32767;
					  clipflag=1;
					}
					if(val<-32768)
					{
					  val=-32768;
					  clipflag=1;
					}
					*ptr=val;
					ptr+=vi.channels;
				  }
				}
			
				if(clipflag)
				  fprintf(stderr,"Clipping in frame %ld\n",(long)(vd.sequence));
				
				
				fwrite(convbuffer,2*vi.channels,bout,stdout);
				
				vorbis_synthesis_read(&vd,bout); /* tell libvorbis how
								   many samples we
							   actually consumed */
			  }	    
			}
		  }
		  if(ogg_page_eos(&og))
			  eos=1;
		}
      }
	  if(!eos)
	  {
		buffer=ogg_sync_buffer(&oy,4096);
		bytes=fread(buffer,1,4096,pFile);
		ogg_sync_wrote(&oy,bytes);
		if(bytes==0)
			eos=1;
	  }
	}
    
    /* clean up this logical bitstream; before exit we see if we're
       followed by another [chained] */

    ogg_stream_clear(&os);
  
    /* ogg_page and ogg_packet structs always point to storage in
       libvorbis.  They're never freed or manipulated directly */
    
    vorbis_block_clear(&vb);
    vorbis_dsp_clear(&vd);
	vorbis_comment_clear(&vc);
    vorbis_info_clear(&vi);  /* must be called last */
  }

  /* OK, clean up the framer */
  ogg_sync_clear(&oy);
  
  fprintf(stderr,"Done.\n");
  return(0);
}
Exemple #6
0
void test_pack(const int *pl, const int **headers){
  unsigned char *data=_ogg_malloc(1024*1024); /* for scripted test cases only */
  long inptr=0;
  long outptr=0;
  long deptr=0;
  long depacket=0;
  long granule_pos=7,pageno=0;
  int i,j,packets,pageout=0;
  int eosflag=0;
  int bosflag=0;

  ogg_stream_reset(&os_en);
  ogg_stream_reset(&os_de);
  ogg_sync_reset(&oy);

  for(packets=0;;packets++)if(pl[packets]==-1)break;

  for(i=0;i<packets;i++){
    /* construct a test packet */
    ogg_packet op;
    int len=pl[i];
    
    op.packet=data+inptr;
    op.bytes=len;
    op.e_o_s=(pl[i+1]<0?1:0);
    op.granulepos=granule_pos;

    granule_pos+=1024;

    for(j=0;j<len;j++)data[inptr++]=i+j;

    /* submit the test packet */
    ogg_stream_packetin(&os_en,&op);

    /* retrieve any finished pages */
    {
      ogg_page og;
      
      while(ogg_stream_pageout(&os_en,&og)){
	/* We have a page.  Check it carefully */

	fprintf(stderr,"%ld, ",pageno);

	if(headers[pageno]==NULL){
	  fprintf(stderr,"coded too many pages!\n");
	  exit(1);
	}

	check_page(data+outptr,headers[pageno],&og);

	outptr+=og.body_len;
	pageno++;

	/* have a complete page; submit it to sync/decode */

	{
	  ogg_page og_de;
	  ogg_packet op_de,op_de2;
	  char *buf=ogg_sync_buffer(&oy,og.header_len+og.body_len);
	  memcpy(buf,og.header,og.header_len);
	  memcpy(buf+og.header_len,og.body,og.body_len);
	  ogg_sync_wrote(&oy,og.header_len+og.body_len);

	  while(ogg_sync_pageout(&oy,&og_de)>0){
	    /* got a page.  Happy happy.  Verify that it's good. */
	    
	    check_page(data+deptr,headers[pageout],&og_de);
	    deptr+=og_de.body_len;
	    pageout++;

	    /* submit it to deconstitution */
	    ogg_stream_pagein(&os_de,&og_de);

	    /* packets out? */
	    while(ogg_stream_packetpeek(&os_de,&op_de2)>0){
	      ogg_stream_packetpeek(&os_de,NULL);
	      ogg_stream_packetout(&os_de,&op_de); /* just catching them all */
	      
	      /* verify peek and out match */
	      if(memcmp(&op_de,&op_de2,sizeof(ogg_packet))){
		fprintf(stderr,"packetout != packetpeek! pos=%ld\n",
			depacket);
		exit(1);
	      }

	      /* verify the packet! */
	      /* check data */
	      if(memcmp(data+depacket,op_de.packet,op_de.bytes)){
		fprintf(stderr,"packet data mismatch in decode! pos=%ld\n",
			depacket);
		exit(1);
	      }
	      /* check bos flag */
	      if(bosflag==0 && op_de.b_o_s==0){
		fprintf(stderr,"b_o_s flag not set on packet!\n");
		exit(1);
	      }
	      if(bosflag && op_de.b_o_s){
		fprintf(stderr,"b_o_s flag incorrectly set on packet!\n");
		exit(1);
	      }
	      bosflag=1;
	      depacket+=op_de.bytes;
	      
	      /* check eos flag */
	      if(eosflag){
		fprintf(stderr,"Multiple decoded packets with eos flag!\n");
		exit(1);
	      }

	      if(op_de.e_o_s)eosflag=1;

	      /* check granulepos flag */
	      if(op_de.granulepos!=-1){
		fprintf(stderr," granule:%ld ",(long)op_de.granulepos);
	      }
	    }
	  }
	}
      }
    }
  }
  _ogg_free(data);
  if(headers[pageno]!=NULL){
    fprintf(stderr,"did not write last page!\n");
    exit(1);
  }
  if(headers[pageout]!=NULL){
    fprintf(stderr,"did not decode last page!\n");
    exit(1);
  }
  if(inptr!=outptr){
    fprintf(stderr,"encoded page data incomplete!\n");
    exit(1);
  }
  if(inptr!=deptr){
    fprintf(stderr,"decoded page data incomplete!\n");
    exit(1);
  }
  if(inptr!=depacket){
    fprintf(stderr,"decoded packet data incomplete!\n");
    exit(1);
  }
  if(!eosflag){
    fprintf(stderr,"Never got a packet with EOS set!\n");
    exit(1);
  }
  fprintf(stderr,"ok.\n");
}
Exemple #7
0
FLAC__OggDecoderAspectReadStatus FLAC__ogg_decoder_aspect_read_callback_wrapper(FLAC__OggDecoderAspect *aspect, FLAC__byte buffer[], size_t *bytes, FLAC__OggDecoderAspectReadCallbackProxy read_callback, const FLAC__StreamDecoder *decoder, void *client_data)
{
	static const size_t OGG_BYTES_CHUNK = 8192;
	const size_t bytes_requested = *bytes;

	/*
	 * The FLAC decoding API uses pull-based reads, whereas Ogg decoding
	 * is push-based.  In libFLAC, when you ask to decode a frame, the
	 * decoder will eventually call the read callback to supply some data,
	 * but how much it asks for depends on how much free space it has in
	 * its internal buffer.  It does not try to grow its internal buffer
	 * to accomodate a whole frame because then the internal buffer size
	 * could not be limited, which is necessary in embedded applications.
	 *
	 * Ogg however grows its internal buffer until a whole page is present;
	 * only then can you get decoded data out.  So we can't just ask for
	 * the same number of bytes from Ogg, then pass what's decoded down to
	 * libFLAC.  If what libFLAC is asking for will not contain a whole
	 * page, then we will get no data from ogg_sync_pageout(), and at the
	 * same time cannot just read more data from the client for the purpose
	 * of getting a whole decoded page because the decoded size might be
	 * larger than libFLAC's internal buffer.
	 *
	 * Instead, whenever this read callback wrapper is called, we will
	 * continually request data from the client until we have at least one
	 * page, and manage pages internally so that we can send pieces of
	 * pages down to libFLAC in such a way that we obey its size
	 * requirement.  To limit the amount of callbacks, we will always try
	 * to read in enough pages to return the full number of bytes
	 * requested.
	 */
	*bytes = 0;
	while (*bytes < bytes_requested && !aspect->end_of_stream) {
		if (aspect->have_working_page) {
			if (aspect->have_working_packet) {
				size_t n = bytes_requested - *bytes;
				if ((size_t)aspect->working_packet.bytes <= n) {
					/* the rest of the packet will fit in the buffer */
					n = aspect->working_packet.bytes;
					memcpy(buffer, aspect->working_packet.packet, n);
					*bytes += n;
					buffer += n;
					aspect->have_working_packet = false;
				}
				else {
					/* only n bytes of the packet will fit in the buffer */
					memcpy(buffer, aspect->working_packet.packet, n);
					*bytes += n;
					buffer += n;
					aspect->working_packet.packet += n;
					aspect->working_packet.bytes -= n;
				}
			}
			else {
				/* try and get another packet */
				const int ret = ogg_stream_packetout(&aspect->stream_state, &aspect->working_packet);
				if (ret > 0) {
					aspect->have_working_packet = true;
					/* if it is the first header packet, check for magic and a supported Ogg FLAC mapping version */
					if (aspect->working_packet.bytes > 0 && aspect->working_packet.packet[0] == FLAC__OGG_MAPPING_FIRST_HEADER_PACKET_TYPE) {
						const FLAC__byte *b = aspect->working_packet.packet;
						const unsigned header_length =
							FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH +
							FLAC__OGG_MAPPING_MAGIC_LENGTH +
							FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH +
							FLAC__OGG_MAPPING_VERSION_MINOR_LENGTH +
							FLAC__OGG_MAPPING_NUM_HEADERS_LENGTH;
						if (aspect->working_packet.bytes < (long)header_length)
							return FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC;
						b += FLAC__OGG_MAPPING_PACKET_TYPE_LENGTH;
						if (memcmp(b, FLAC__OGG_MAPPING_MAGIC, FLAC__OGG_MAPPING_MAGIC_LENGTH))
							return FLAC__OGG_DECODER_ASPECT_READ_STATUS_NOT_FLAC;
						b += FLAC__OGG_MAPPING_MAGIC_LENGTH;
						aspect->version_major = (unsigned)(*b);
						b += FLAC__OGG_MAPPING_VERSION_MAJOR_LENGTH;
						aspect->version_minor = (unsigned)(*b);
						if (aspect->version_major != 1)
							return FLAC__OGG_DECODER_ASPECT_READ_STATUS_UNSUPPORTED_MAPPING_VERSION;
						aspect->working_packet.packet += header_length;
						aspect->working_packet.bytes -= header_length;
					}
				}
				else if (ret == 0) {
					aspect->have_working_page = false;
				}
				else { /* ret < 0 */
					/* lost sync, we'll leave the working page for the next call */
					return FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC;
				}
			}
		}
		else {
			/* try and get another page */
			const int ret = ogg_sync_pageout(&aspect->sync_state, &aspect->working_page);
			if (ret > 0) {
				/* got a page, grab the serial number if necessary */
				if(aspect->need_serial_number) {
					aspect->stream_state.serialno = aspect->serial_number = ogg_page_serialno(&aspect->working_page);
					aspect->need_serial_number = false;
				}
				if(ogg_stream_pagein(&aspect->stream_state, &aspect->working_page) == 0) {
					aspect->have_working_page = true;
					aspect->have_working_packet = false;
				}
				/* else do nothing, could be a page from another stream */
			}
			else if (ret == 0) {
				/* need more data */
				const size_t ogg_bytes_to_read = max(bytes_requested - *bytes, OGG_BYTES_CHUNK);
				char *oggbuf = ogg_sync_buffer(&aspect->sync_state, ogg_bytes_to_read);

				if(0 == oggbuf) {
					return FLAC__OGG_DECODER_ASPECT_READ_STATUS_MEMORY_ALLOCATION_ERROR;
				}
				else {
					size_t ogg_bytes_read = ogg_bytes_to_read;

					switch(read_callback(decoder, (FLAC__byte*)oggbuf, &ogg_bytes_read, client_data)) {
						case FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK:
							break;
						case FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM:
							aspect->end_of_stream = true;
							break;
						case FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT:
							return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ABORT;
						default:
							FLAC__ASSERT(0);
					}

					if(ogg_sync_wrote(&aspect->sync_state, ogg_bytes_read) < 0) {
						/* double protection; this will happen if the read callback returns more bytes than the max requested, which would overflow Ogg's internal buffer */
						FLAC__ASSERT(0);
						return FLAC__OGG_DECODER_ASPECT_READ_STATUS_ERROR;
					}
				}
			}
			else { /* ret < 0 */
				/* lost sync, bail out */
				return FLAC__OGG_DECODER_ASPECT_READ_STATUS_LOST_SYNC;
			}
		}
	}

	if (aspect->end_of_stream && *bytes == 0) {
		return FLAC__OGG_DECODER_ASPECT_READ_STATUS_END_OF_STREAM;
	}

	return FLAC__OGG_DECODER_ASPECT_READ_STATUS_OK;
}
Exemple #8
0
static int ReadHeader(OGG_context *ctx, SYS_FILEHANDLE file)
{
	const size_t size = 4096;
	int theError;
	void *buffer;
	int i, serialNo;
	size_t bytes = 0;

	ogg_sync_init(&ctx->oy); /* Now we can read pages */
	/* submit a 4k block to libvorbis' Ogg layer */
	if (!ctx->eos)
	{
		buffer = ogg_sync_buffer(&ctx->oy, (int32_t)size);
		bytes = FIO_cur->fread(buffer, 1 , size, file);
		ogg_sync_wrote(&ctx->oy, (int32_t)size);
	}

	/* Get the first page. */
	theError = ogg_sync_pageout(&ctx->oy, &ctx->og);
	SYS_ASSERT(theError == 1);
	if (theError!=1)
	{
		/* error case.	Must not be Vorbis data */
		SYS_ASSERT(bytes<size);
		return 0;
	}

	/* Get the serial number and set up the rest of decode. */
	/* serialno first; use it to set up a logical stream */
	serialNo = ogg_page_serialno(&ctx->og);
	theError = ogg_stream_init(&ctx->os, serialNo);
	SYS_ASSERT(theError==0);

	/* extract the initial header from the first page and verify that the
	   Ogg bitstream is in fact Vorbis data */

	/* I handle the initial header first instead of just having the code
	   read all three Vorbis headers at once because reading the initial
	   header is an easy way to identify a Vorbis bitstream and it's
	   useful to see that functionality seperated out. */

	theError = ogg_stream_pagein(&ctx->os, &ctx->og);
	SYS_ASSERT(theError>=0);
	if (theError < 0)
	{
		/* error; stream version mismatch perhaps */
		return 0;
	}
	theError = ogg_stream_packetout(&ctx->os, &ctx->op);
	SYS_ASSERT(theError == 1);
	if (theError!=1)
	{
		/* no page? must not be vorbis */
		return 0;
	}
	theError = vorbis_synthesis_headerin(&ctx->vi, &ctx->vc, &ctx->op);
	SYS_ASSERT(theError >=0);
	if (theError < 0)
	{
		return 0;
	}
	/* At this point, we're sure we're Vorbis.	We've set up the logical
	   (Ogg) bitstream decoder.  Get the comment and codebook headers and
	   set up the Vorbis decoder */

	/* The next two packets in order are the comment and codebook headers.
	   They're likely large and may span multiple pages.  Thus we reead
	   and submit data until we get our two pacakets, watching that no
	   pages are missing.  If a page is missing, error out; losing a
	   header page is the only place where missing data is fatal. */

	i=0;
	while(i<2)
	{
		while(i<2)
		{
			int result = ogg_sync_pageout(&ctx->oy, &ctx->og);
			if (result==0)
				break; /* Need more data */
			/* Don't complain about missing or corrupt data yet.  We'll
			catch it at the packet output phase */
			if(result==1)
			{
				ogg_stream_pagein(&ctx->os, &ctx->og); /* we can ignore any errors here
				as they'll also become apparent
				at packetout */
				while(i<2)
				{
					result = ogg_stream_packetout(&ctx->os, &ctx->op);
					if (result==0)
						break;
					if (result<0)
					{
						/* Uh oh; data at some point was corrupted or missing!
						We can't tolerate that in a header.  Die. */
						SYS_ASSERT(0);
						return 0;
					}
					vorbis_synthesis_headerin(&ctx->vi, &ctx->vc, &ctx->op);
					i++;
				}
			}
		}
		buffer = ogg_sync_buffer(&ctx->oy, (int32_t)size);
		bytes  = FIO_cur->fread(buffer, 1 , size, file);
		SYS_ASSERT(!(bytes==0 && i<2));
		ogg_sync_wrote(&ctx->oy,(int32_t) size);
	}
	/* OK, got and parsed all three headers. Initialize the Vorbis
	 packet->PCM decoder. */
	vorbis_synthesis_init(&ctx->vd, &ctx->vi); /*	central decode state */
	vorbis_block_init(&ctx->vd, &ctx->vb);		/*	local state for most of the decode
													so multiple block decodes can
													proceed in parallel.  We could init
													multiple vorbis_block structures
													for vd here */

	ctx->input_size = size;
	ctx->state = 0;
	return 1;
}
Exemple #9
0
static int play_vorbis(lua_State *lstate) {
	char buf[BLOCKSIZE];
	char *pt, *oggbuf, **comm, *mark;
	int n, sock, sr_err, port;
	const char *host, *mount;
	VORBIS_FEED *feed;
	lua_pushstring(lstate, "host");
	lua_gettable(lstate, -2);
	lua_pushstring(lstate, "port");
	lua_gettable(lstate, -3);
	lua_pushstring(lstate, "mount");
	lua_gettable(lstate, -4);
	mount = lua_tostring(lstate, -1);
	port = lua_tointeger(lstate, -2);
	host = lua_tostring(lstate, -3);
	sock = stream_connect(host, port, mount, buf, &mark);
	lua_pop(lstate, 3);
	if (sock == 0) {
		lua_pop(lstate, 1);
		return 0;
		}
	lua_pushstring(lstate, "intern");
	lua_gettable(lstate, -2);
	feed = (VORBIS_FEED *)lua_touserdata(lstate, -1);
	lua_pop(lstate, 1);
	feed->base.sock = sock;
	pthread_mutex_init(&(feed->base.thread_lock), NULL);
	pthread_cond_init(&(feed->base.data_ready), NULL);
	ogg_sync_init(&(feed->oy));
	oggbuf = ogg_sync_buffer(&(feed->oy), BLOCKSIZE);
	n = BLOCKSIZE - (mark - buf);
	memcpy(oggbuf, mark, n);
	read_sock(feed->base.sock, oggbuf + n, BLOCKSIZE - n);
	ogg_sync_wrote(&(feed->oy), BLOCKSIZE);
	if ((n = ogg_sync_pageout(&(feed->oy), &(feed->og))) != 1) {
		logmsg("out of data: %d\n", n);
		free_vorbis((FEED *)feed);
		lua_pop(lstate, 1);
		return 0;
		}
	ogg_stream_init(&(feed->os), ogg_page_serialno(&(feed->og)));
	vorbis_info_init(&(feed->vi));
	vorbis_comment_init(&(feed->vc));
	if (ogg_stream_pagein(&(feed->os), &(feed->og)) < 1) {
		logmsg("error reading first ogg page\n");
		//free_feed(feed);
		//return 0;
		}
	if (ogg_stream_packetout(&(feed->os), &(feed->op)) != 1) {
		logmsg("error reading first header packet\n");
		free_vorbis((FEED *)feed);
		lua_pop(lstate, 1);
		return 0;
		}
	if (vorbis_synthesis_headerin(&(feed->vi),
			&(feed->vc), &(feed->op)) < 0) {
		logmsg("stream is not vorbis\n");
		free_vorbis((FEED *)feed);
		lua_pop(lstate, 1);
		return 0;
		}
	vorbis_headers(feed);
	add_table(lstate, "info");
	add_table(lstate, "comments");
	comm = feed->vc.user_comments;
	while (*comm) {
		if ((pt = index(*comm, '=')) != NULL) {
			*pt++ = '\0';
			set_string(lstate, *comm, pt);
			}
		++comm;
		}
	lua_pop(lstate, 1); // comments
	feed->base.channels = feed->vi.channels;
	set_integer(lstate, "channels", feed->base.channels);
	set_integer(lstate, "srate", feed->vi.rate);
	lua_pop(lstate, 1); // info
	feed->base.cbuf = new_ringbuf(feed->vi.rate, feed->base.channels,
			BUFSECS, 0.333, 0.667);
	if (jack_sr != feed->vi.rate) {
		feed->base.converter = src_new(SRC_SINC_MEDIUM_QUALITY,
				feed->base.channels, &sr_err);
		feed->base.src_data_in = (float *)malloc(SRC_DATA_FRAMES *
				feed->base.channels * sizeof(float));
		feed->base.src_data.data_in = feed->base.src_data_in;
		feed->base.src_data_remain = 0;
		feed->base.src_data.src_ratio = jack_sr
					/ (double)feed->vi.rate;
		feed->base.src_data_out = (float *)malloc(
				(int)ceil(SRC_DATA_FRAMES *
				feed->base.channels * sizeof(float) *
				feed->base.src_data.src_ratio));
		}
	feed->base.init = 1;
	lua_pop(lstate, 1);
	pthread_create(&(feed->base.thread_id), NULL, vorbis_thread, feed);
	return 0;
	}
Exemple #10
0
static gboolean
xmms_speex_init (xmms_xform_t *xform)
{
	gint pe;

	xmms_config_property_t *val;
	xmms_speex_data_t *data;
	xmms_error_t error;

	g_return_val_if_fail (xform, FALSE);

	data = g_new0 (xmms_speex_data_t, 1);
	g_return_val_if_fail (data, FALSE);

	xmms_xform_private_data_set (xform, data);

	ogg_sync_init (&data->sync_state);
	speex_bits_init (&data->speex_bits);

	/* Find the speex header */

	while (42) {
		gint ret;

		data->ogg_data = ogg_sync_buffer (&data->sync_state, 1024);
		ret = xmms_xform_read (xform, data->ogg_data, 1024, &error);
		ogg_sync_wrote (&data->sync_state, ret);

		if (ret <= 0) {
			return FALSE;
		}

		if (ogg_sync_pageout (&data->sync_state, &data->ogg_page) == 1) {
			break;
		}
	}

	ogg_stream_init (&data->stream_state, ogg_page_serialno (&data->ogg_page));

	if (ogg_stream_pagein (&data->stream_state, &data->ogg_page) < 0) {
		return FALSE;
	}

	if (ogg_stream_packetout (&data->stream_state, &data->ogg_packet) != 1) {
		return FALSE;
	}

	data->speexheader = speex_packet_to_header ((char *)data->ogg_packet.packet,
	                                            data->ogg_packet.bytes);
	data->speex_state = speex_decoder_init (speex_mode_list[data->speexheader->mode]);

	val = xmms_xform_config_lookup (xform, "perceptual_enhancer");
	pe = xmms_config_property_get_int (val);
	speex_decoder_ctl (data->speex_state, SPEEX_SET_ENH, &pe);

	ogg_sync_pageout (&data->sync_state, &data->ogg_page);
	ogg_stream_pagein (&data->stream_state, &data->ogg_page);
	ogg_stream_packetout (&data->stream_state, &data->ogg_packet);

	data->samples_buf = g_new (gint16,
	                           data->speexheader->frames_per_packet *
	                           data->speexheader->frame_size *
	                           data->speexheader->nb_channels);
	data->samples_start = data->samples_buf;
	data->samples_count = 0;

	xmms_speex_read_metadata (xform, data);

	xmms_xform_outdata_type_add (xform,
	                             XMMS_STREAM_TYPE_MIMETYPE,
	                             "audio/pcm",
	                             XMMS_STREAM_TYPE_FMT_FORMAT,
	                             XMMS_SAMPLE_FORMAT_S16,
	                             XMMS_STREAM_TYPE_FMT_CHANNELS,
	                             data->speexheader->nb_channels,
	                             XMMS_STREAM_TYPE_FMT_SAMPLERATE,
	                             data->speexheader->rate,
	                             XMMS_STREAM_TYPE_END);

	return TRUE;
}
Exemple #11
0
// Decode
static int Decode(void *context, const void *dataRAW,
					size_t sizeRAW, void **ppdataPCM, size_t *sizePCM)
{
	OGG_context *ctx = (OGG_context*)context;

	*sizePCM = 0;
	*ppdataPCM = 0;

	if (!dataRAW)
		return 0;

	switch(ctx->state)
	{
		// Sync buffer
		case 0xff:
		{
			sysMemCpy(ogg_sync_buffer(&ctx->oy, (int32_t)sizeRAW), dataRAW, sizeRAW);
			ctx->input_size = sizeRAW;
			ogg_sync_wrote(&ctx->oy, (int32_t)ctx->input_size);
			ctx->state = 0;
		}
		break;
		// Sync page out
		case 0:
		{
			int result = ogg_sync_pageout(&ctx->oy, &ctx->og);
			if (result == 0)
			{
				ctx->state = 0xff;
			}
			else
			if (result < 0)
			{
				ctx->state = -1;
			}
			else
			{
				ogg_stream_pagein(&ctx->os, &ctx->og); /* can safely ignore errors at this point */
				ctx->state = 1;
			}
		}
		break;

		// Stream packet out
		case 1:
		{
			int result = ogg_stream_packetout(&ctx->os, &ctx->op);
			if (result == 0)
			{
				ctx->state = 0;
			}
			else
			if (result < 0)
			{
				ctx->state = -2;
			}
			else
			{
				/* we have a packet.	Decode it */
				if (vorbis_synthesis(&ctx->vb, &ctx->op)==0) /* test for success! */
					vorbis_synthesis_blockin(&ctx->vd, &ctx->vb);
				ctx->state = 3;
			}
		}
		break;

		// synthetis pcm out
		case 3:
		{
			size_t samples;
			float **pcm;
			samples = vorbis_synthesis_pcmout(&ctx->vd, &pcm);
			if (samples<=0)
			{
				ctx->state = 1;
			}
			else
			{
				size_t convsize = ctx->input_size / ctx->vi.channels;
				size_t bytesCount = samples < convsize ? samples : convsize;
				SYS_ASSERT(bytesCount < OGG_BUFFER_SIZE);
#ifdef SUPPORT_IEEE_AUDIO
				DeinterleaveAudio(ctx->uncompressed, pcm, ctx->vi.channels, bytesCount);
				*sizePCM = 4 * ctx->vi.channels * bytesCount;
#else
				ConvertFloatToInteger(ctx->uncompressed, pcm, ctx->vi.channels, bytesCount);
				*sizePCM = 2 * ctx->vi.channels * bytesCount;
#endif
				/* tell libvorbis how many samples we actually consumed */
				vorbis_synthesis_read(&ctx->vd, (int32_t)bytesCount);
				*ppdataPCM = ctx->uncompressed;
			}
		}
		break;

		// Invalid state
		default:
			SYS_ASSERT(0);
			return -1;
		break;

	}
	return ctx->state != 0xff ? 1 : 0;
}
Exemple #12
0
static gint
xmms_speex_read (xmms_xform_t *xform, gpointer buf, gint len,
                 xmms_error_t *err)
{
	gint ret = 0, n;
	gfloat outfloat [2000];
	gint16 *outbuf = (gint16 *) buf;
	xmms_speex_data_t *data;
	xmms_error_t error;
	SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;

	g_return_val_if_fail (xform, -1);

	data = xmms_xform_private_data_get (xform);
	g_return_val_if_fail (data, -1);

	/* convert from bytes to samples */
	len /= 2;

	/* first, copy already decoded samples over if we have any. */
	if (data->samples_count) {
		n = MIN (data->samples_count, len);

		memcpy (outbuf, data->samples_start, n * 2);
		data->samples_count -= n;

		if (!data->samples_count) {
			data->samples_start = data->samples_buf;
		} else {
			data->samples_start += n;
		}

		/* convert from samples to bytes */
		return n * 2;
	}

	while (42) {
		gint samples_per_frame;

		samples_per_frame = data->speexheader->frame_size *
		                    data->speexheader->nb_channels;

		while (ogg_stream_packetout (&data->stream_state, &data->ogg_packet) == 1) {
			gint frame;

			speex_bits_read_from (&data->speex_bits,
			                      (char *)data->ogg_packet.packet,
			                      data->ogg_packet.bytes);

			for (frame = 0; frame < data->speexheader->frames_per_packet; frame++) {
				gint cnt;

				speex_decode (data->speex_state, &data->speex_bits, outfloat);

				if (data->speexheader->nb_channels == 2) {
					speex_decode_stereo (outfloat, data->speexheader->frame_size,&stereo);
				}

				n = MIN (samples_per_frame, len);

				/* copy as many samples to the output buffer as
				 * possible.
				 */
				for (cnt = 0; cnt < n; cnt++) {
					*outbuf++ = outfloat[cnt];
					len--;
					ret += 2;
				}

				/* store the remaining samples for later use */
				for (; cnt < samples_per_frame; cnt++) {
					data->samples_buf[data->samples_count++] =
						outfloat[cnt];
				}
			}

			return ret;
		}

		/* Need more data */

		do {
			gint ret;

			data->ogg_data = ogg_sync_buffer (&data->sync_state, 200);
			ret = xmms_xform_read (xform, data->ogg_data, 200, &error);
			ogg_sync_wrote (&data->sync_state, ret);

			if (ret <= 0) {
				return ret;
			}
		} while (ogg_sync_pageout (&data->sync_state, &data->ogg_page) != 1);

		ogg_stream_pagein (&data->stream_state, &data->ogg_page);
	}
}
/** central buffer management function 
  * @param openmaxStandComp the component handle
  * @param inputbuffer contains the input ogg file content
  * @param outputbuffer is returned along with its output pcm file content that is produced as a result of this function execution
  */
void omx_vorbisdec_component_BufferMgmtCallbackVorbis(OMX_COMPONENTTYPE *openmaxStandComp, OMX_BUFFERHEADERTYPE* inputbuffer, OMX_BUFFERHEADERTYPE* outputbuffer) {

  omx_vorbisdec_component_PrivateType* omx_vorbisdec_component_Private = openmaxStandComp->pComponentPrivate;
  OMX_U8* outputCurrBuffer;
  OMX_U32 outputLength;
  OMX_S32 result;  
  float **pcm;
  OMX_S32 samples;
  OMX_S32 i, j;
  OMX_S32 bout;
  OMX_S32 clipflag=0;
  int val;
  float  *mono;
  int eos=0;
  char *vorbis_buffer;
  ogg_int16_t convbuffer[4096];

 
  DEBUG(DEB_LEV_FULL_SEQ, "input buf %x filled len : %d \n", (int)inputbuffer->pBuffer, (int)inputbuffer->nFilledLen);  
  /** Fill up the current input buffer when a new buffer has arrived */
  if(omx_vorbisdec_component_Private->isNewBuffer) {
    omx_vorbisdec_component_Private->inputCurrBuffer = inputbuffer->pBuffer;
    omx_vorbisdec_component_Private->inputCurrLength = inputbuffer->nFilledLen;
    omx_vorbisdec_component_Private->positionInOutBuf = 0;

    DEBUG(DEB_LEV_SIMPLE_SEQ, "new -- input buf %x filled len : %d \n", (int)inputbuffer->pBuffer, (int)inputbuffer->nFilledLen);  

    /** for each new input buffer --- copy buffer content into into ogg sync state structure data */
    vorbis_buffer = ogg_sync_buffer(&omx_vorbisdec_component_Private->oy, inputbuffer->nAllocLen);
    memcpy(vorbis_buffer, inputbuffer->pBuffer, inputbuffer->nFilledLen);
    ogg_sync_wrote(&omx_vorbisdec_component_Private->oy, inputbuffer->nFilledLen);
    DEBUG(DEB_LEV_FULL_SEQ,"***** bytes read to buffer (of first header): %d \n",(int)inputbuffer->nFilledLen);
  }
  outputCurrBuffer = outputbuffer->pBuffer;
  outputLength = outputbuffer->nAllocLen;
  outputbuffer->nFilledLen = 0;
  outputbuffer->nOffset = 0;
  
  if(omx_vorbisdec_component_Private->packetNumber < 3) {
    omx_vorbisdec_component_Private->isNewBuffer = 0;
    if(omx_vorbisdec_component_Private->packetNumber == 0) {
      DEBUG(DEB_LEV_SIMPLE_SEQ, "in processing the first header buffer\n");      
      if(ogg_sync_pageout(&omx_vorbisdec_component_Private->oy, &omx_vorbisdec_component_Private->og) != 1)  {
        DEBUG(DEB_LEV_ERR, "this input stream is not an Ogg stream\n");
        return;
      }  
      ogg_stream_init(&omx_vorbisdec_component_Private->os, ogg_page_serialno(&omx_vorbisdec_component_Private->og));    
      vorbis_info_init(&omx_vorbisdec_component_Private->vi);
      vorbis_comment_init(&omx_vorbisdec_component_Private->vc);

      if(ogg_stream_pagein(&omx_vorbisdec_component_Private->os, &omx_vorbisdec_component_Private->og) < 0)  {
        DEBUG(DEB_LEV_ERR, "Error reading first page of Ogg bitstream data.\n");
        return;
      }
      if(ogg_stream_packetout(&omx_vorbisdec_component_Private->os, &omx_vorbisdec_component_Private->op) != 1)  {
        DEBUG(DEB_LEV_ERR, "Error reading initial header packet.\n");
        return;
      }
      
      omx_vorbisdec_component_Private->packetNumber++;

      if(vorbis_synthesis_headerin(&omx_vorbisdec_component_Private->vi, &omx_vorbisdec_component_Private->vc, &omx_vorbisdec_component_Private->op) < 0)  {
        DEBUG(DEB_LEV_ERR, "This Ogg bitstream does not contain Vorbis audio data\n");
        return;
      }  
    }

    while(omx_vorbisdec_component_Private->packetNumber < 3)
    {
      int result=ogg_sync_pageout(&omx_vorbisdec_component_Private->oy,&omx_vorbisdec_component_Private->og);
      if(result==0) { //break; /* Need more data */
        omx_vorbisdec_component_Private->isNewBuffer = 1;
        inputbuffer->nFilledLen = 0;
        return;
      }
      /* Don't complain about missing or corrupt data yet.  We'll
      catch it at the packet output phase */
      if(result==1) 
      {
        ogg_stream_pagein(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->og);
        /* we can ignore any errors here as they'll also become apparent at packetout */
        while(omx_vorbisdec_component_Private->packetNumber < 3) {
          result=ogg_stream_packetout(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->op);
          if(result==0)break;
          if(result<0) {
          /* Uh oh; data at some point was corrupted or missing!
            We can't tolerate that in a header.  Die. */
            DEBUG(DEB_LEV_ERR,"Corrupt secondary header.  Exiting.\n");
            break;
          }//end if
          omx_vorbisdec_component_Private->packetNumber++;
          vorbis_synthesis_headerin(&omx_vorbisdec_component_Private->vi,&omx_vorbisdec_component_Private->vc,&omx_vorbisdec_component_Private->op);
        }//end while
      }//end if
    }//end while

    omx_vorbisdec_component_Private->isNewBuffer = 1;
    inputbuffer->nFilledLen = 0;
    return;

  }

  /* A Vorbis logical bitstream begins with 3 headers. Once the last of these has been processed,
   * we can report the metadata and set up the output audio port appropriately. */
  if(omx_vorbisdec_component_Private->packetNumber == 3) {
    /* Throw the comments plus a few lines about the bitstream we're decoding */
    {
      // ptr should be declared earlier//
      char **ptr=omx_vorbisdec_component_Private->vc.user_comments;
      while(*ptr){
        DEBUG(DEB_LEV_ERR,"%s\n",*ptr);
        ++ptr;
      }
      DEBUG(DEB_LEV_ERR,"Bitstream is %d channel, %ldHz\n",omx_vorbisdec_component_Private->vi.channels,omx_vorbisdec_component_Private->vi.rate);
      DEBUG(DEB_LEV_ERR,"Encoded by: %s\n\n",omx_vorbisdec_component_Private->vc.vendor);
    }

    /* Update pAudioVorbis settings */
    omx_vorbisdec_component_Private->pAudioVorbis.nSampleRate = omx_vorbisdec_component_Private->vi.rate;
    omx_vorbisdec_component_Private->pAudioVorbis.nChannels = omx_vorbisdec_component_Private->vi.channels;

    /* Update audio port settings for this Vorbis bitstream */
    if ((omx_vorbisdec_component_Private->pAudioPcmMode.nSamplingRate != omx_vorbisdec_component_Private->pAudioVorbis.nSampleRate) ||
        (omx_vorbisdec_component_Private->pAudioPcmMode.nChannels != omx_vorbisdec_component_Private->pAudioVorbis.nChannels)) {
      omx_vorbisdec_component_Private->pAudioPcmMode.nSamplingRate = omx_vorbisdec_component_Private->pAudioVorbis.nSampleRate;
      omx_vorbisdec_component_Private->pAudioPcmMode.nChannels = omx_vorbisdec_component_Private->pAudioVorbis.nChannels;

      /*Send Port Settings changed call back*/
      (*(omx_vorbisdec_component_Private->callbacks->EventHandler))
        (openmaxStandComp,
        omx_vorbisdec_component_Private->callbackData,
        OMX_EventPortSettingsChanged, /* The command was completed */
        0,
        1, /* This is the output port index */
        NULL);
    }

    omx_vorbisdec_component_Private->convsize=inputbuffer->nFilledLen/omx_vorbisdec_component_Private->vi.channels;
    /* OK, got and parsed all three headers. Initialize the Vorbis
    packet->PCM decoder. */
    vorbis_synthesis_init(&omx_vorbisdec_component_Private->vd,&omx_vorbisdec_component_Private->vi); /* central decode state */
    vorbis_block_init(&omx_vorbisdec_component_Private->vd,&omx_vorbisdec_component_Private->vb);/* local state for most of the decode
                               so multiple block decodes can
                               proceed in parallel.  We could init
                               multiple vorbis_block structures
                               for vd here */
  }
  DEBUG(DEB_LEV_FULL_SEQ,"***** now the decoding will start *****\n");

  if(omx_vorbisdec_component_Private->isNewBuffer)  {
    omx_vorbisdec_component_Private->isNewBuffer=0;
    int result=ogg_sync_pageout(&omx_vorbisdec_component_Private->oy,&omx_vorbisdec_component_Private->og);
    DEBUG(DEB_LEV_FULL_SEQ," --->  page (read in decoding) - header len :  %ld body len : %ld \n",omx_vorbisdec_component_Private->og.header_len,omx_vorbisdec_component_Private->og.body_len);
    if(result == 0)  {
      omx_vorbisdec_component_Private->isNewBuffer = 1;
      inputbuffer->nFilledLen = 0;
      return;
    }
    if(result<0)
    { 
      /* missing or corrupt data at this page position */
      DEBUG(DEB_LEV_ERR,"Corrupt or missing data in bitstream; continuing...\n");
    }
    else {
      ogg_stream_pagein(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->og); /* can safely ignore errors at */
    }
  }
  
  result=ogg_stream_packetout(&omx_vorbisdec_component_Private->os,&omx_vorbisdec_component_Private->op);
  DEBUG(DEB_LEV_FULL_SEQ," packet length (read in decoding a particular page): %ld \n",omx_vorbisdec_component_Private->op.bytes);
  if(result == 0)  {
    omx_vorbisdec_component_Private->isNewBuffer = 1;
    inputbuffer->nFilledLen = 0;
    return;
  }
  if(result<0)
  {
    /* missing or corrupt data at this page position */
    /* no reason to complain; already complained above */
    DEBUG(DEB_LEV_ERR,"Corrupt or missing data in bitstream; continuing...\n");
  } else {
    /* we have a packet.  Decode it */
    omx_vorbisdec_component_Private->packetNumber++;

    if(vorbis_synthesis(&omx_vorbisdec_component_Private->vb,&omx_vorbisdec_component_Private->op)==0) /* test for success! */
    vorbis_synthesis_blockin(&omx_vorbisdec_component_Private->vd,&omx_vorbisdec_component_Private->vb);
    /**pcm is a multichannel float vector.  In stereo, for
      example, pcm[0] is left, and pcm[1] is right.  samples is
      the size of each channel.  Convert the float values
      (-1.<=range<=1.) to whatever PCM format and write it out */

    while((samples=vorbis_synthesis_pcmout(&omx_vorbisdec_component_Private->vd,&pcm))>0)
    {
      bout=(samples<omx_vorbisdec_component_Private->convsize?samples:omx_vorbisdec_component_Private->convsize);

      /* convert floats to 16 bit signed ints (host order) and interleave */
      for(i=0;i<omx_vorbisdec_component_Private->vi.channels;i++)
      {
        ogg_int16_t *ptr=convbuffer+i;
        mono=pcm[i];
        for(j=0;j<bout;j++)
        {
#if 1
          val=mono[j]*32767.f;
#else     /* optional dither */
          val=mono[j]*32767.f+drand48()-0.5f;
#endif
          /* might as well guard against clipping */
          if(val>32767)
          {
            val=32767;
            clipflag=1;
          }
          if(val<-32768)
          {
            val=-32768;
            clipflag=1;
          }
          *ptr=val;
          ptr+=omx_vorbisdec_component_Private->vi.channels;
        }
      }

      outputbuffer->nFilledLen=2*omx_vorbisdec_component_Private->vi.channels*bout;
      memcpy(outputCurrBuffer,(char *)convbuffer,outputbuffer->nFilledLen);

      if(clipflag) {
        DEBUG(DEB_LEV_FULL_SEQ,"Clipping in frame %ld\n",(long)(omx_vorbisdec_component_Private->vd.sequence));
      }
      vorbis_synthesis_read(&omx_vorbisdec_component_Private->vd,bout); /* tell libvorbis how many samples we actually consumed */
    }
  }
  if(ogg_page_eos(&omx_vorbisdec_component_Private->og)) {
    DEBUG(DEB_LEV_FULL_SEQ, "In %s EOS Detected\n",__func__);
    eos=1;
  }
 
  DEBUG(DEB_LEV_FULL_SEQ, "One output buffer %x len=%d is full returning\n", (int)outputbuffer->pBuffer, (int)outputbuffer->nFilledLen);  
}
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for reading.
 * \param s File that points to on disk storage of the OGG/Vorbis data.
 * \return The new filestream.
 */
static int ogg_vorbis_open(struct ast_filestream *s)
{
	int i;
	int bytes;
	int result;
	char **ptr;
	char *buffer;
	struct vorbis_desc *tmp = (struct vorbis_desc *)s->_private;

	tmp->writing = 0;

	ogg_sync_init(&tmp->oy);

	buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
	bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
	ogg_sync_wrote(&tmp->oy, bytes);

	result = ogg_sync_pageout(&tmp->oy, &tmp->og);
	if (result != 1) {
		if(bytes < BLOCK_SIZE) {
			ast_log(LOG_ERROR, "Run out of data...\n");
		} else {
			ast_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
		}
		ogg_sync_clear(&tmp->oy);
		return -1;
	}
	
	ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og));
	vorbis_info_init(&tmp->vi);
	vorbis_comment_init(&tmp->vc);

	if (ogg_stream_pagein(&tmp->os, &tmp->og) < 0) { 
		ast_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
error:
		ogg_stream_clear(&tmp->os);
		vorbis_comment_clear(&tmp->vc);
		vorbis_info_clear(&tmp->vi);
		ogg_sync_clear(&tmp->oy);
		return -1;
	}
	
	if (ogg_stream_packetout(&tmp->os, &tmp->op) != 1) { 
		ast_log(LOG_ERROR, "Error reading initial header packet.\n");
		goto error;
	}
	
	if (vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0) { 
		ast_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n");
		goto error;
	}
	
	for (i = 0; i < 2 ; ) {
		while (i < 2) {
			result = ogg_sync_pageout(&tmp->oy, &tmp->og);
			if (result == 0)
				break;
			if (result == 1) {
				ogg_stream_pagein(&tmp->os, &tmp->og);
				while(i < 2) {
					result = ogg_stream_packetout(&tmp->os,&tmp->op);
					if(result == 0)
						break;
					if(result < 0) {
						ast_log(LOG_ERROR, "Corrupt secondary header.  Exiting.\n");
						goto error;
					}
					vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op);
					i++;
				}
			}
		}

		buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
		bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
		if (bytes == 0 && i < 2) {
			ast_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n");
			goto error;
		}
		ogg_sync_wrote(&tmp->oy, bytes);
	}
	
	for (ptr = tmp->vc.user_comments; *ptr; ptr++)
		ast_debug(1, "OGG/Vorbis comment: %s\n", *ptr);
		ast_debug(1, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate);
		ast_debug(1, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor);

	if (tmp->vi.channels != 1) {
		ast_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
		goto error;
	}
	
	if (tmp->vi.rate != DEFAULT_SAMPLE_RATE) {
		ast_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
		vorbis_block_clear(&tmp->vb);
		vorbis_dsp_clear(&tmp->vd);
		goto error;
	}
	
	vorbis_synthesis_init(&tmp->vd, &tmp->vi);
	vorbis_block_init(&tmp->vd, &tmp->vb);

	return 0;
}
Exemple #15
0
static UINT ogg_dec(GETSND snd, short *dst) {

	__OV	*ov;
	int		result;
	char	*buffer;
	int		bytes;
	float	**pcm;
	int		samples;
	int		i;
	int		j;
	float	*mono;
	short	*ptr;
	long	val;

	ov = (__OV *)snd->snd;

	do {
		switch(ov->phase) {
			case OVPHASE_HEAD:
				result = ogg_sync_pageout(&ov->oy, &ov->og);
				if (result > 0) {
					ogg_stream_pagein(&ov->os, &ov->og);
					ov->phase = OVPHASE_STREAMIN;
				}
				else if (result == 0) {
					ov->phase = OVPHASE_NEXT;
				}
				else {
					TRACEOUT(("Corrupt or missing data in bitstream"));
				}
				break;

			case OVPHASE_STREAMIN:
				result = ogg_stream_packetout(&ov->os, &ov->op);
				if (result > 0) {
					if (vorbis_synthesis(&ov->vb, &ov->op) == 0) {
						vorbis_synthesis_blockin(&ov->vd, &ov->vb);
					}
					ov->phase = OVPHASE_GETPCM;
				}
				else if (result == 0) {
					if (!ogg_page_eos(&ov->og)) {
						ov->phase = OVPHASE_NEXT;
					}
					else {
						ov->phase = OVPHASE_CLOSE;
					}
				}
				break;

			case OVPHASE_GETPCM:
				samples = vorbis_synthesis_pcmout(&ov->vd, &pcm);
				if (samples > 0) {
					if (samples > (int)snd->blocksamples) {
						samples = (int)snd->blocksamples;
					}
					for (i=0; i<ov->vi.channels; i++) {
						ptr = dst + i;
						mono = pcm[i];
						for (j=0; j<samples; j++) {
							val = (long)(mono[j] * 32767.f);
							if (val > 32767) {
								val = 32767;
							}
							if (val < -32768) {
								val = -32768;
							}
							*ptr = (short)val;
							ptr += ov->vi.channels;
						}
					}
					vorbis_synthesis_read(&ov->vd, samples);
					return((UINT)samples);
				}
				ov->phase = OVPHASE_STREAMIN;
				break;

			case OVPHASE_NEXT:
				buffer = ogg_sync_buffer(&ov->oy, 4096);
				bytes = snd_read(snd, buffer, 4096);
				ogg_sync_wrote(&ov->oy, bytes);
#if 1
				ov->phase = OVPHASE_HEAD;
#else
				if (bytes) {
					ov->phase = OVPHASE_HEAD;
				}
				else {
					ov->phase = OVPHASE_CLOSE;
				}
#endif
				break;

			case OVPHASE_CLOSE:
				return(0);
		}
	} while(1);
}
Exemple #16
0
int sndogg_open(SMIXTRACK trk) {

	__OV	*ov;
	char	*buffer;
	UINT	r;
	int		bytes;
	int 	i;
	int		result;

	ov = (__OV *)_MALLOC(sizeof(__OV), "__OV");
	if (ov == NULL) {
		goto ovopn_next;
	}
	ZeroMemory(ov, sizeof(__OV));

	r = sndmix_dataload(trk, trk->maxdatas);
	if ((r == (UINT)-1) || (r == 0)) {
		goto ovopn_next2;
	}
	buffer = ogg_sync_buffer(&ov->oy, trk->maxdatas);
	CopyMemory(buffer, trk->data, r);
	ogg_sync_wrote(&ov->oy, (int)r);

	if (ogg_sync_pageout(&ov->oy, &ov->og) != 1) {
		TRACEOUT(("Input does not appear to be an Ogg bitstream."));
		goto ovopn_next2;
	}
	ogg_stream_init(&ov->os, ogg_page_serialno(&ov->og));
	sndmix_datatrash(trk, (UINT)-1);

	vorbis_info_init(&ov->vi);
	vorbis_comment_init(&ov->vc);
	if (ogg_stream_pagein(&ov->os, &ov->og) < 0) {
		TRACEOUT(("Error reading first page of Ogg bitstream data."));
		goto ovopn_err1;
	}

	if (ogg_stream_packetout(&ov->os, &ov->op) != 1) {
		TRACEOUT(("Error reading initial header packet."));
		goto ovopn_err1;
	}

	if (vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op) < 0) {
		TRACEOUT(("This Ogg bitstream does not contain Vorbis audio data."));
		goto ovopn_err1;
	}

	i = 0;
	while(i < 2) {
		while(i < 2) {
			result = ogg_sync_pageout(&ov->oy, &ov->og);
			if (result == 0) {
				break;
			}
			if (result == 1) {
				ogg_stream_pagein(&ov->os, &ov->og);
				while(i < 2) {
					result = ogg_stream_packetout(&ov->os, &ov->op);
					if (result == 0) {
						break;
					}
					if (result < 0) {
						TRACEOUT(("Corrupt secondary header. Exiting."));
						goto ovopn_err1;
					}
					vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op);
					i++;
				}
			}
		}
		buffer = ogg_sync_buffer(&ov->oy, 4096);
		bytes = sndmix_dataread(trk, buffer, 4096);
		if ((bytes == 0) && (i < 2)) {
			TRACEOUT(("End of file before finding all Vorbis headers!"));
			return(SNDMIX_FAILURE);
		}
		ogg_sync_wrote(&ov->oy, bytes);
	}

	trk->snd = ov;
	trk->dec = (DECFN)ogg_dec;
	trk->decend = ogg_decend;
	trk->samprate = ov->vi.rate;
	trk->channels = ov->vi.channels;
	trk->block = 4096;
	trk->blksamp = 4096 / ov->vi.channels;
	trk->bit = 16;
#if defined(SOUND_MOREINFO)
	trk->bps = 0;
	trk->fmt = WAVEFMT_OGG;
	CopyMemory(trk->info, "Ogg vorbis", 11);
#endif

	vorbis_synthesis_init(&ov->vd, &ov->vi);
	vorbis_block_init(&ov->vd, &ov->vb);
	return(SNDMIX_SUCCESS);

ovopn_err1:
	ogg_sync_clear(&ov->oy);
	_MFREE(ov);
	return(SNDMIX_FAILURE);

ovopn_next2:
	_MFREE(ov);

ovopn_next:
	return(SNDMIX_NOTSUPPORT);
}
Exemple #17
0
/* Read the speex header. Return 0 on error. */
static int read_speex_header (struct spx_data *data)
{
	int packet_count = 0;
	int stream_init = 0;
	char *buf;
	ssize_t nb_read;
	int header_packets = 2;

	while (packet_count < header_packets) {

		/* Get the ogg buffer for writing */
		buf = ogg_sync_buffer (&data->oy, 200);

		/* Read bitstream from input file */
		nb_read = io_read (data->stream, buf, 200);

		if (nb_read < 0) {
			decoder_error (&data->error, ERROR_FATAL, 0,
					"Can't open speex file: IO error: %s",
					io_strerror(data->stream));
			return 0;
		}

		if (nb_read == 0) {
			decoder_error (&data->error, ERROR_FATAL, 0,
					"Can't open speex header");
			return 0;
		}

		ogg_sync_wrote (&data->oy, nb_read);

		/* Loop for all complete pages we got (most likely only one) */
		while (ogg_sync_pageout(&data->oy, &data->og) == 1) {

			if (stream_init == 0) {
				ogg_stream_init(&data->os,
						ogg_page_serialno(&data->og));
				stream_init = 1;
			}

			/* Add page to the bitstream */
			ogg_stream_pagein (&data->os, &data->og);

			/* Extract all available packets FIXME: EOS! */
			while (ogg_stream_packetout(&data->os, &data->op) == 1) {

				/* If first packet, process as Speex header */
				if (packet_count == 0) {
					data->st = process_header (data);

					if (!data->st) {
						ogg_stream_clear (&data->os);
						return 0;
					}

					data->rate = data->header->rate;
					data->nchannels
						= data->header->nb_channels;
					data->frames_per_packet
						= data->header->frames_per_packet;
					/*data->vbr = data->header->vbr; */

					if (!data->frames_per_packet)
						data->frames_per_packet=1;

					data->output = xmalloc (data->frame_size *
							data->nchannels *
							data->frames_per_packet *
							sizeof(int16_t));
					data->output_start = 0;
					data->output_left = 0;

					header_packets += data->header->extra_headers;
				}
				else if (packet_count == 1) {
					data->comment_packet_len
						= data->op.bytes;
					data->comment_packet = xmalloc (
							sizeof(char) *
							data->comment_packet_len);
					memcpy (data->comment_packet,
							data->op.packet,
							data->comment_packet_len);
				}

				packet_count++;
			}
		}
	}

	return 1;
}
Exemple #18
0
static UINT ogg_dec(SMIXTRACK trk, SINT16 *dst) {

	__OV	*ov;
	int		result;
	char	*buffer;
	UINT	r;
	float	**pcm;
	int		samples;
	int		i;
	int		j;
	float	*mono;
	SINT16	*ptr;
	SINT32	val;

	ov = (__OV *)trk->snd;

	do {
		switch(ov->phase) {
			case OVPHASE_HEAD:
				result = ogg_sync_pageout(&ov->oy, &ov->og);
				if (result > 0) {
					ogg_stream_pagein(&ov->os, &ov->og);
					ov->phase = OVPHASE_STREAMIN;
				}
				else if (result == 0) {
					ov->phase = OVPHASE_NEXT;
				}
				else {
					TRACEOUT(("Corrupt or missing data in bitstream"));
				}
				break;

			case OVPHASE_STREAMIN:
				result = ogg_stream_packetout(&ov->os, &ov->op);
				if (result > 0) {
					if (vorbis_synthesis(&ov->vb, &ov->op) == 0) {
						vorbis_synthesis_blockin(&ov->vd, &ov->vb);
					}
					ov->phase = OVPHASE_GETPCM;
				}
				else if (result == 0) {
					if (!ogg_page_eos(&ov->og)) {
						ov->phase = OVPHASE_NEXT;
					}
					else {
						ov->phase = OVPHASE_CLOSE;
					}
				}
				break;

			case OVPHASE_GETPCM:
				samples = vorbis_synthesis_pcmout(&ov->vd, &pcm);
				if (samples > 0) {
					if (samples > (int)trk->blksamp) {
						samples = (int)trk->blksamp;
					}
					for (i=0; i<ov->vi.channels; i++) {
						ptr = dst + i;
						mono = pcm[i];
						for (j=0; j<samples; j++) {
							val = (long)(mono[j] * 32767.f);
							if (val > 32767) {
								val = 32767;
							}
							if (val < -32768) {
								val = -32768;
							}
							*ptr = (SINT16)val;
							ptr += ov->vi.channels;
						}
					}
					vorbis_synthesis_read(&ov->vd, samples);
					return((UINT)samples);
				}
				ov->phase = OVPHASE_STREAMIN;
				break;

			case OVPHASE_NEXT:
				buffer = ogg_sync_buffer(&ov->oy, trk->block);
				r = sndmix_dataread(trk, buffer, trk->block);
				ogg_sync_wrote(&ov->oy, (int)r);
				if (r) {
					ov->phase = OVPHASE_HEAD;
				}
				else {
					ov->phase = OVPHASE_CLOSE;
				}
				break;

			case OVPHASE_CLOSE:
				ov->phase = OVPHASE_HEAD;			// ��[��
				return(0);
		}
	} while(1);
}
Exemple #19
0
int main(void){

  ogg_stream_init(&os_en,0x04030201);
  ogg_stream_init(&os_de,0x04030201);
  ogg_sync_init(&oy);

  /* Exercise each code path in the framing code.  Also verify that
     the checksums are working.  */

  {
    /* 17 only */
    const int packets[]={17, -1};
    const int *headret[]={head1_0,NULL};
    
    fprintf(stderr,"testing single page encoding... ");
    test_pack(packets,headret);
  }

  {
    /* 17, 254, 255, 256, 500, 510, 600 byte, pad */
    const int packets[]={17, 254, 255, 256, 500, 510, 600, -1};
    const int *headret[]={head1_1,head2_1,NULL};
    
    fprintf(stderr,"testing basic page encoding... ");
    test_pack(packets,headret);
  }

  {
    /* nil packets; beginning,middle,end */
    const int packets[]={0,17, 254, 255, 0, 256, 0, 500, 510, 600, 0, -1};
    const int *headret[]={head1_2,head2_2,NULL};
    
    fprintf(stderr,"testing basic nil packets... ");
    test_pack(packets,headret);
  }

  {
    /* large initial packet */
    const int packets[]={4345,259,255,-1};
    const int *headret[]={head1_3,head2_3,NULL};
    
    fprintf(stderr,"testing initial-packet lacing > 4k... ");
    test_pack(packets,headret);
  }

  {
    /* continuing packet test */
    const int packets[]={0,4345,259,255,-1};
    const int *headret[]={head1_4,head2_4,head3_4,NULL};
    
    fprintf(stderr,"testing single packet page span... ");
    test_pack(packets,headret);
  }

  /* page with the 255 segment limit */
  {

    const int packets[]={0,10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,10,
		   10,10,10,10,10,10,10,50,-1};
    const int *headret[]={head1_5,head2_5,head3_5,NULL};
    
    fprintf(stderr,"testing max packet segments... ");
    test_pack(packets,headret);
  }

  {
    /* packet that overspans over an entire page */
    const int packets[]={0,100,9000,259,255,-1};
    const int *headret[]={head1_6,head2_6,head3_6,head4_6,NULL};
    
    fprintf(stderr,"testing very large packets... ");
    test_pack(packets,headret);
  }

  {
    /* term only page.  why not? */
    const int packets[]={0,100,4080,-1};
    const int *headret[]={head1_7,head2_7,head3_7,NULL};
    
    fprintf(stderr,"testing zero data page (1 nil packet)... ");
    test_pack(packets,headret);
  }



  {
    /* build a bunch of pages for testing */
    unsigned char *data=_ogg_malloc(1024*1024);
    int pl[]={0,100,4079,2956,2057,76,34,912,0,234,1000,1000,1000,300,-1};
    int inptr=0,i,j;
    ogg_page og[5];
    
    ogg_stream_reset(&os_en);

    for(i=0;pl[i]!=-1;i++){
      ogg_packet op;
      int len=pl[i];
      
      op.packet=data+inptr;
      op.bytes=len;
      op.e_o_s=(pl[i+1]<0?1:0);
      op.granulepos=(i+1)*1000;

      for(j=0;j<len;j++)data[inptr++]=i+j;
      ogg_stream_packetin(&os_en,&op);
    }

    _ogg_free(data);

    /* retrieve finished pages */
    for(i=0;i<5;i++){
      if(ogg_stream_pageout(&os_en,&og[i])==0){
	fprintf(stderr,"Too few pages output building sync tests!\n");
	exit(1);
      }
      copy_page(&og[i]);
    }

    /* Test lost pages on pagein/packetout: no rollback */
    {
      ogg_page temp;
      ogg_packet test;

      fprintf(stderr,"Testing loss of pages... ");

      ogg_sync_reset(&oy);
      ogg_stream_reset(&os_de);
      for(i=0;i<5;i++){
	memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
	       og[i].header_len);
	ogg_sync_wrote(&oy,og[i].header_len);
	memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
	ogg_sync_wrote(&oy,og[i].body_len);
      }

      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      /* skip */
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);

      /* do we get the expected results/packets? */
      
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,0,0,0);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,100,1,-1);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,4079,2,3000);
      if(ogg_stream_packetout(&os_de,&test)!=-1){
	fprintf(stderr,"Error: loss of page did not return error\n");
	exit(1);
      }
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,76,5,-1);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,34,6,-1);
      fprintf(stderr,"ok.\n");
    }

    /* Test lost pages on pagein/packetout: rollback with continuation */
    {
      ogg_page temp;
      ogg_packet test;

      fprintf(stderr,"Testing loss of pages (rollback required)... ");

      ogg_sync_reset(&oy);
      ogg_stream_reset(&os_de);
      for(i=0;i<5;i++){
	memcpy(ogg_sync_buffer(&oy,og[i].header_len),og[i].header,
	       og[i].header_len);
	ogg_sync_wrote(&oy,og[i].header_len);
	memcpy(ogg_sync_buffer(&oy,og[i].body_len),og[i].body,og[i].body_len);
	ogg_sync_wrote(&oy,og[i].body_len);
      }

      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);
      ogg_sync_pageout(&oy,&temp);
      /* skip */
      ogg_sync_pageout(&oy,&temp);
      ogg_stream_pagein(&os_de,&temp);

      /* do we get the expected results/packets? */
      
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,0,0,0);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,100,1,-1);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,4079,2,3000);
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,2956,3,4000);
      if(ogg_stream_packetout(&os_de,&test)!=-1){
	fprintf(stderr,"Error: loss of page did not return error\n");
	exit(1);
      }
      if(ogg_stream_packetout(&os_de,&test)!=1)error();
      checkpacket(&test,300,13,14000);
      fprintf(stderr,"ok.\n");
    }
    
    /* the rest only test sync */
    {
      ogg_page og_de;
      /* Test fractional page inputs: incomplete capture */
      fprintf(stderr,"Testing sync on partial inputs... ");
      ogg_sync_reset(&oy);
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     3);
      ogg_sync_wrote(&oy,3);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      /* Test fractional page inputs: incomplete fixed header */
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+3,
	     20);
      ogg_sync_wrote(&oy,20);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      /* Test fractional page inputs: incomplete header */
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+23,
	     5);
      ogg_sync_wrote(&oy,5);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      /* Test fractional page inputs: incomplete body */
      
      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+28,
	     og[1].header_len-28);
      ogg_sync_wrote(&oy,og[1].header_len-28);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,1000);
      ogg_sync_wrote(&oy,1000);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body+1000,
	     og[1].body_len-1000);
      ogg_sync_wrote(&oy,og[1].body_len-1000);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
      
      fprintf(stderr,"ok.\n");
    }

    /* Test fractional page inputs: page + incomplete capture */
    {
      ogg_page og_de;
      fprintf(stderr,"Testing sync on 1+partial inputs... ");
      ogg_sync_reset(&oy); 

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     og[1].header_len);
      ogg_sync_wrote(&oy,og[1].header_len);

      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     20);
      ogg_sync_wrote(&oy,20);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
      if(ogg_sync_pageout(&oy,&og_de)>0)error();

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header+20,
	     og[1].header_len-20);
      ogg_sync_wrote(&oy,og[1].header_len-20);
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      fprintf(stderr,"ok.\n");
    }
    
    /* Test recapture: garbage + page */
    {
      ogg_page og_de;
      fprintf(stderr,"Testing search for capture... ");
      ogg_sync_reset(&oy); 
      
      /* 'garbage' */
      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     og[1].header_len);
      ogg_sync_wrote(&oy,og[1].header_len);

      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
	     20);
      ogg_sync_wrote(&oy,20);
      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();
      if(ogg_sync_pageout(&oy,&og_de)>0)error();

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header+20,
	     og[2].header_len-20);
      ogg_sync_wrote(&oy,og[2].header_len-20);
      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
	     og[2].body_len);
      ogg_sync_wrote(&oy,og[2].body_len);
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      fprintf(stderr,"ok.\n");
    }

    /* Test recapture: page + garbage + page */
    {
      ogg_page og_de;
      fprintf(stderr,"Testing recapture... ");
      ogg_sync_reset(&oy); 

      memcpy(ogg_sync_buffer(&oy,og[1].header_len),og[1].header,
	     og[1].header_len);
      ogg_sync_wrote(&oy,og[1].header_len);

      memcpy(ogg_sync_buffer(&oy,og[1].body_len),og[1].body,
	     og[1].body_len);
      ogg_sync_wrote(&oy,og[1].body_len);

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
	     og[2].header_len);
      ogg_sync_wrote(&oy,og[2].header_len);

      memcpy(ogg_sync_buffer(&oy,og[2].header_len),og[2].header,
	     og[2].header_len);
      ogg_sync_wrote(&oy,og[2].header_len);

      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      memcpy(ogg_sync_buffer(&oy,og[2].body_len),og[2].body,
	     og[2].body_len-5);
      ogg_sync_wrote(&oy,og[2].body_len-5);

      memcpy(ogg_sync_buffer(&oy,og[3].header_len),og[3].header,
	     og[3].header_len);
      ogg_sync_wrote(&oy,og[3].header_len);

      memcpy(ogg_sync_buffer(&oy,og[3].body_len),og[3].body,
	     og[3].body_len);
      ogg_sync_wrote(&oy,og[3].body_len);

      if(ogg_sync_pageout(&oy,&og_de)>0)error();
      if(ogg_sync_pageout(&oy,&og_de)<=0)error();

      fprintf(stderr,"ok.\n");
    }
  }    

  return(0);
}
Exemple #20
0
int main(int argc, char **argv)
{
   int c;
   int option_index = 0;
   char *inFile, *outFile;
   FILE *fin, *fout=NULL;
   short out[MAX_FRAME_SIZE];
   short output[MAX_FRAME_SIZE];
   int frame_size=0, granule_frame_size=0;
   void *st=NULL;
   CELTMode *mode=NULL;
   int packet_count=0;
   int stream_init = 0;
   int quiet = 0;
   ogg_int64_t page_granule=0, last_granule=0;
   int skip_samples=0, page_nb_packets;
   struct option long_options[] =
   {
      {"help", no_argument, NULL, 0},
      {"quiet", no_argument, NULL, 0},
      {"version", no_argument, NULL, 0},
      {"version-short", no_argument, NULL, 0},
      {"rate", required_argument, NULL, 0},
      {"mono", no_argument, NULL, 0},
      {"stereo", no_argument, NULL, 0},
      {"packet-loss", required_argument, NULL, 0},
      {0, 0, 0, 0}
   };
   ogg_sync_state oy;
   ogg_page       og;
   ogg_packet     op;
   ogg_stream_state os;
   int enh_enabled;
   int nframes=2;
   int print_bitrate=0;
   int close_in=0;
   int eos=0;
   int forceMode=-1;
   int audio_size=0;
   float loss_percent=-1;
   int channels=-1;
   int rate=0;
   int extra_headers=0;
   int wav_format=0;
   int lookahead=0;
   int celt_serialno = -1;
   int firstpacket = 1;

   enh_enabled = 1;

   /*Process options*/
   while(1)
   {
      c = getopt_long (argc, argv, "hvV",
                       long_options, &option_index);
      if (c==-1)
         break;
      
      switch(c)
      {
      case 0:
         if (strcmp(long_options[option_index].name,"help")==0)
         {
            usage();
            exit(0);
         } else if (strcmp(long_options[option_index].name,"quiet")==0)
         {
            quiet = 1;
         } else if (strcmp(long_options[option_index].name,"version")==0)
         {
            version();
            exit(0);
         } else if (strcmp(long_options[option_index].name,"version-short")==0)
         {
            version_short();
            exit(0);
         } else if (strcmp(long_options[option_index].name,"mono")==0)
         {
            channels=1;
         } else if (strcmp(long_options[option_index].name,"stereo")==0)
         {
            channels=2;
         } else if (strcmp(long_options[option_index].name,"rate")==0)
         {
            rate=atoi (optarg);
         } else if (strcmp(long_options[option_index].name,"packet-loss")==0)
         {
            loss_percent = atof(optarg);
         }
         break;
      case 'h':
         usage();
         exit(0);
         break;
      case 'v':
         version();
         exit(0);
         break;
      case 'V':
         print_bitrate=1;
         break;
      case '?':
         usage();
         exit(1);
         break;
      }
   }
   if (argc-optind!=2 && argc-optind!=1)
   {
      usage();
      exit(1);
   }
   inFile=argv[optind];

   if (argc-optind==2)
      outFile=argv[optind+1];
   else
      outFile = "";
   wav_format = strlen(outFile)>=4 && (
                                       strcmp(outFile+strlen(outFile)-4,".wav")==0
                                       || strcmp(outFile+strlen(outFile)-4,".WAV")==0);
   /*Open input file*/
   if (strcmp(inFile, "-")==0)
   {
#if defined WIN32 || defined _WIN32
      _setmode(_fileno(stdin), _O_BINARY);
#endif
      fin=stdin;
   }
   else 
   {
      fin = fopen(inFile, "rb");
      if (!fin)
      {
         perror(inFile);
         exit(1);
      }
      close_in=1;
   }


   /*Init Ogg data struct*/
   ogg_sync_init(&oy);
   
   /*Main decoding loop*/
   
   while (1)
   {
      char *data;
      int i, nb_read;
      /*Get the ogg buffer for writing*/
      data = ogg_sync_buffer(&oy, 200);
      /*Read bitstream from input file*/
      nb_read = fread(data, sizeof(char), 200, fin);      
      ogg_sync_wrote(&oy, nb_read);

      /*Loop for all complete pages we got (most likely only one)*/
      while (ogg_sync_pageout(&oy, &og)==1)
      {
         if (stream_init == 0) {
            ogg_stream_init(&os, ogg_page_serialno(&og));
            stream_init = 1;
         }
	 if (ogg_page_serialno(&og) != os.serialno) {
	    /* so all streams are read. */
	    ogg_stream_reset_serialno(&os, ogg_page_serialno(&og));
	 }
         /*Add page to the bitstream*/
         ogg_stream_pagein(&os, &og);
         page_granule = ogg_page_granulepos(&og);
         page_nb_packets = ogg_page_packets(&og);
         if (page_granule>0 && frame_size)
         {
            /* FIXME: shift the granule values if --force-* is specified */
            skip_samples = frame_size*(page_nb_packets*granule_frame_size*nframes - (page_granule-last_granule))/granule_frame_size;
            if (ogg_page_eos(&og))
               skip_samples = -skip_samples;
            /*else if (!ogg_page_bos(&og))
               skip_samples = 0;*/
         } else
         {
            skip_samples = 0;
         }
         /*printf ("page granulepos: %d %d %d\n", skip_samples, page_nb_packets, (int)page_granule);*/
         last_granule = page_granule;
         /*Extract all available packets*/
         while (!eos && ogg_stream_packetout(&os, &op) == 1)
         {
	    if (op.bytes>=8 && !memcmp(op.packet, "CELT    ", 8)) {
	       celt_serialno = os.serialno;
	    }
	    if (celt_serialno == -1 || os.serialno != celt_serialno)
	       break;
            /*If first packet, process as CELT header*/
            if (packet_count==0)
            {
               st = process_header(&op, enh_enabled, &frame_size, &granule_frame_size, &rate, &nframes, forceMode, &channels, &lookahead, &extra_headers, quiet, &mode);
               if (!st)
                  exit(1);
               if (!nframes)
                  nframes=1;
               fout = out_file_open(outFile, rate, &channels);

            } else if (packet_count==1)
            {
               if (!quiet)
                  print_comments((char*)op.packet, op.bytes);
            } else if (packet_count<=1+extra_headers)
            {
               /* Ignore extra headers */
            } else {
               int lost=0;
               if (loss_percent>0 && 100*((float)rand())/RAND_MAX<loss_percent)
                  lost=1;

               /*End of stream condition*/
               if (op.e_o_s && os.serialno == celt_serialno) /* don't care for anything except celt eos */
                  eos=1;
	       
               {
                  int ret;
                  /*Decode frame*/
                  if (!lost)
                     ret = celt_decode(st, (unsigned char*)op.packet, op.bytes, output, frame_size);
                  else
                     ret = celt_decode(st, NULL, 0, output, frame_size);

                  /*for (i=0;i<frame_size*channels;i++)
                    printf ("%d\n", (int)output[i]);*/

                  if (ret<0)
                  {
                     fprintf (stderr, "Decoding error: %s\n", celt_strerror(ret));
                     break;
                  }

                  if (print_bitrate) {
                     celt_int32 tmp=op.bytes;
                     char ch=13;
                     fputc (ch, stderr);
                     fprintf (stderr, "Bitrate in use: %d bytes/packet     ", tmp);
                  }
                  /*Convert to short and save to output file*/
                  if (strlen(outFile)!=0)
                  {
                     for (i=0;i<frame_size*channels;i++)
                        out[i]=le_short(output[i]);
                  } else {
                     for (i=0;i<frame_size*channels;i++)
                        out[i]=output[i];
                  }
                  {
                     int frame_offset = 0;
                     int new_frame_size = frame_size;
                     /*printf ("packet %d %d\n", packet_no, skip_samples);*/
                     /*fprintf (stderr, "packet %d %d %d\n", packet_no, skip_samples, lookahead);*/
                     if (firstpacket == 1)
                     {
                        /*printf ("chopping first packet\n");*/
                        new_frame_size -= lookahead;
                        frame_offset = lookahead;
                        firstpacket = 0;
                     }
                     if (new_frame_size>0)
                     {  
#if defined WIN32 || defined _WIN32
                        if (strlen(outFile)==0)
                           WIN_Play_Samples (out+frame_offset*channels, sizeof(short) * new_frame_size*channels);
                        else
#endif
                           fwrite(out+frame_offset*channels, sizeof(short), new_frame_size*channels, fout);
                  
                        audio_size+=sizeof(short)*new_frame_size*channels;
                     }
                  }
               }
            }
            packet_count++;
         }
      }
      if (feof(fin))
         break;

   }

   if (fout && wav_format)
   {
      if (fseek(fout,4,SEEK_SET)==0)
      {
         int tmp;
         tmp = le_int(audio_size+36);
         fwrite(&tmp,4,1,fout);
         if (fseek(fout,32,SEEK_CUR)==0)
         {
            tmp = le_int(audio_size);
            fwrite(&tmp,4,1,fout);
         } else
         {
            fprintf (stderr, "First seek worked, second didn't\n");
         }
      } else {
         fprintf (stderr, "Cannot seek on wave file, size will be incorrect\n");
      }
   }

   if (st)
   {
      celt_decoder_destroy(st);
      celt_mode_destroy(mode);
   } else {
      fprintf (stderr, "This doesn't look like a CELT file\n");
   }
   if (stream_init)
      ogg_stream_clear(&os);
   ogg_sync_clear(&oy);

#if defined WIN32 || defined _WIN32
   if (strlen(outFile)==0)
      WIN_Audio_close ();
#endif

   if (close_in)
      fclose(fin);
   if (fout != NULL)
      fclose(fout);   

   return 0;
}
Exemple #21
0
status_t
OggReader::FindLastPages()
{
	TRACE("OggReader::FindLastPages\n");
	bigtime_t start_time = system_time();

	status_t result = B_ERROR;

	const int read_size = 256*256;

	ogg_page page;
	ogg_sync_state sync;
	ogg_sync_init(&sync);

	off_t right = fSeekable->Seek(0, SEEK_END);
	off_t left = right;
	// we assume the common case is that the last pages are near the end
	uint serial_count = 0;
	while (serial_count < fCookies.size()) {
		int offset;
		ssize_t bytes = 0;
		while ((offset = ogg_sync_pageseek(&sync, &page)) <= 0) {
			left += -offset;
			if (offset == 0) {
				off_t pos = fSeekable->Position();
				if (pos >= right || bytes == 0) {
					if (left == 0) {
						TRACE("OggReader::FindLastPages: couldn't find some stream's page!!!\n");
						goto done;
					}
					left = max_c(0, left - read_size);
					result = fSeekable->Seek(left, SEEK_SET);
					if (result < 0) {
						goto done;
					}
					ogg_sync_reset(&sync);
				}
				char * buffer = ogg_sync_buffer(&sync, read_size);
				bytes = fSeekable->Read(buffer, read_size);
				if (bytes < 0) {
					TRACE("OggReader::FindLastPages: Read: error\n");
					result = bytes;
					goto done;
				}
				if (ogg_sync_wrote(&sync, bytes) != 0) {
					TRACE("OggReader::FindLastPages: ogg_sync_wrote failed?: error\n");
					goto done;
				}
			}
		}
		off_t current = left;
		do {
			// found a page at "current"
			long serialno = ogg_page_serialno(&page);
			OggSeekable * track = dynamic_cast<OggSeekable*>(fTracks[serialno]);
			if (track == 0) {
				TRACE("OggReader::FindLastPages: unknown serialno == TODO: chaining?\n");
			} else {
				if (track->GetLastPagePosition() == 0) {
					serial_count++;
				}
				track->SetLastPagePosition(current);
			}
			current += page.header_len + page.body_len;
		} while ((current < right) && (ogg_sync_pageout(&sync, &page) == 1));
		right = left;
		ogg_sync_reset(&sync);
	}
	result = B_OK;
done:
	ogg_sync_clear(&sync);
	TRACE("OggReader::FindLastPages took %lld microseconds\n", system_time() - start_time);

	return result;
}
Exemple #22
0
/* main plugin handler for getting a buffer for the queue. In here we
 * just add an incoming page to the codecs and process it until either
 * more data is needed or we prodice a buffer for the queue.
 */
static refbuf_t *ogg_get_buffer (source_t *source)
{
    ogg_state_t *ogg_info = source->format->_state;
    format_plugin_t *format = source->format;
    char *data = NULL;
    int bytes = 0, total = 0;

    while (total < 15000)
    {
        while (1)
        {
            ogg_page page;
            refbuf_t *refbuf = NULL;
            ogg_codec_t *codec = ogg_info->current;

            /* if a codec has just been given a page then process it */
            if (codec && codec->process)
            {
                refbuf = codec->process (ogg_info, codec);
                if (refbuf)
                    return complete_buffer (source, refbuf);

                ogg_info->current = NULL;
            }

            if (ogg_sync_pageout (&ogg_info->oy, &page) > 0)
            {
                if (ogg_page_bos (&page))
                {
                    process_initial_page (source->format, &page);
                }
                else
                {
                    ogg_info->bos_completed = 1;
                    refbuf = process_ogg_page (ogg_info, &page);
                }
                if (ogg_info->error)
                {
                    ERROR0 ("Problem processing stream");
                    source->flags &= ~SOURCE_RUNNING;
                    return NULL;
                }
                if (refbuf)
                    return complete_buffer (source, refbuf);
                continue;
            }
            /* need more stream data */
            break;
        }
        /* we need more data to continue getting pages */
        data = ogg_sync_buffer (&ogg_info->oy, 4096);

        bytes = client_read_bytes (source->client, data, 4096);
        if (bytes <= 0)
        {
            ogg_sync_wrote (&ogg_info->oy, 0);
            source->client->schedule_ms += 50;
            break;
        }
        total += bytes;
        format->read_bytes += bytes;
        rate_add (source->in_bitrate, bytes, source->client->worker->current_time.tv_sec);
        ogg_sync_wrote (&ogg_info->oy, bytes);
    }
    return NULL;
}
/* Helper; just grab some more compressed bitstream and sync it for
   page extraction */
int buffer_data(FILE *in,ogg_sync_state *oy){
  char *buffer=ogg_sync_buffer(oy,4096);
  int bytes=fread(buffer,1,4096,in);
  ogg_sync_wrote(oy,bytes);
  return(bytes);
}
UInt32 SFB::Audio::OggSpeexDecoder::_ReadAudio(AudioBufferList *bufferList, UInt32 frameCount)
{
	if(bufferList->mNumberBuffers != mFormat.mChannelsPerFrame) {
		LOGGER_WARNING("org.sbooth.AudioEngine.Decoder.OggSpeex", "_ReadAudio() called with invalid parameters");
		return 0;
	}

	UInt32 framesRead = 0;

	// Reset output buffer data size
	for(UInt32 i = 0; i < bufferList->mNumberBuffers; ++i)
		bufferList->mBuffers[i].mDataByteSize = 0;

	for(;;) {

		UInt32	framesRemaining	= frameCount - framesRead;
		UInt32	framesToSkip	= (UInt32)(bufferList->mBuffers[0].mDataByteSize / sizeof(float));
		UInt32	framesInBuffer	= (UInt32)(mBufferList->mBuffers[0].mDataByteSize / sizeof(float));
		UInt32	framesToCopy	= std::min(framesInBuffer, framesRemaining);

		// Copy data from the buffer to output
		for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i) {
			float *floatBuffer = (float *)bufferList->mBuffers[i].mData;
			memcpy(floatBuffer + framesToSkip, mBufferList->mBuffers[i].mData, framesToCopy * sizeof(float));
			bufferList->mBuffers[i].mDataByteSize += framesToCopy * sizeof(float);

			// Move remaining data in buffer to beginning
			if(framesToCopy != framesInBuffer) {
				floatBuffer = (float *)mBufferList->mBuffers[i].mData;
				memmove(floatBuffer, floatBuffer + framesToCopy, (framesInBuffer - framesToCopy) * sizeof(float));
			}

			mBufferList->mBuffers[i].mDataByteSize -= framesToCopy * sizeof(float);
		}

		framesRead += framesToCopy;

		// All requested frames were read
		if(framesRead == frameCount)
			break;

		// EOS reached
		if(mSpeexEOSReached)
			break;

		// Attempt to process the desired number of packets
		unsigned packetsDesired = 1;
		while(0 < packetsDesired && !mSpeexEOSReached) {

			// Process any packets in the current page
			while(0 < packetsDesired && !mSpeexEOSReached) {

				// Grab a packet from the streaming layer
				ogg_packet oggPacket;
				int result = ogg_stream_packetout(&mOggStreamState, &oggPacket);
				if(-1 == result) {
					LOGGER_ERR("org.sbooth.AudioEngine.Decoder.OggSpeex", "Ogg Speex decoding error: Ogg loss of streaming");
					break;
				}

				// If result is 0, there is insufficient data to assemble a packet
				if(0 == result)
					break;

				// Otherwise, we got a valid packet for processing
				if(1 == result) {
					if(5 <= oggPacket.bytes && !memcmp(oggPacket.packet, "Speex", 5))
						mSpeexSerialNumber = mOggStreamState.serialno;

					if(-1 == mSpeexSerialNumber || mOggStreamState.serialno != mSpeexSerialNumber)
						break;

					// Ignore the following:
					//  - Speex comments in packet #2
					//  - Extra headers (optionally) in packets 3+
					if(1 != mOggPacketCount && 1 + mExtraSpeexHeaderCount <= mOggPacketCount) {
						// Detect Speex EOS
						if(oggPacket.e_o_s && mOggStreamState.serialno == mSpeexSerialNumber)
							mSpeexEOSReached = true;

						// SPEEX_GET_FRAME_SIZE is in samples
						spx_int32_t speexFrameSize;
						speex_decoder_ctl(mSpeexDecoder, SPEEX_GET_FRAME_SIZE, &speexFrameSize);
						float buffer [(2 == mFormat.mChannelsPerFrame) ? 2 * speexFrameSize : speexFrameSize];

						// Copy the Ogg packet to the Speex bitstream
						speex_bits_read_from(&mSpeexBits, (char *)oggPacket.packet, (int)oggPacket.bytes);

						// Decode each frame in the Speex packet
						for(spx_int32_t i = 0; i < mSpeexFramesPerOggPacket; ++i) {

							result = speex_decode(mSpeexDecoder, &mSpeexBits, buffer);

							// -1 indicates EOS
							if(-1 == result)
								break;
							else if(-2 == result) {
								LOGGER_ERR("org.sbooth.AudioEngine.Decoder.OggSpeex", "Ogg Speex decoding error: possible corrupted stream");
								break;
							}

							if(0 > speex_bits_remaining(&mSpeexBits)) {
								LOGGER_ERR("org.sbooth.AudioEngine.Decoder.OggSpeex", "Ogg Speex decoding overflow: possible corrupted stream");
								break;
							}

							// Normalize the values
							float maxSampleValue = 1u << 15;
							vDSP_vsdiv(buffer, 1, &maxSampleValue, buffer, 1, (vDSP_Length)speexFrameSize);

							// Copy the frames from the decoding buffer to the output buffer, skipping over any frames already decoded
							framesInBuffer = mBufferList->mBuffers[0].mDataByteSize / sizeof(float);
							memcpy((float *)mBufferList->mBuffers[0].mData + framesInBuffer, buffer, (size_t)speexFrameSize * sizeof(float));
							mBufferList->mBuffers[0].mDataByteSize += (size_t)speexFrameSize * sizeof(float);

							// Process stereo channel, if present
							if(2 == mFormat.mChannelsPerFrame) {
								speex_decode_stereo(buffer, speexFrameSize, mSpeexStereoState);
								vDSP_vsdiv(buffer + speexFrameSize, 1, &maxSampleValue, buffer + speexFrameSize, 1, (vDSP_Length)speexFrameSize);

								memcpy((float *)mBufferList->mBuffers[1].mData + framesInBuffer, buffer + speexFrameSize, (size_t)speexFrameSize * sizeof(float));
								mBufferList->mBuffers[1].mDataByteSize += (size_t)speexFrameSize * sizeof(float);
							}

							// Packet processing finished
							--packetsDesired;
						}
					}

					++mOggPacketCount;
				}
			}

			// Grab a new Ogg page for processing, if necessary
			if(!mSpeexEOSReached && 0 < packetsDesired) {
				while(1 != ogg_sync_pageout(&mOggSyncState, &mOggPage)) {
					// Get the ogg buffer for writing
					char *data = ogg_sync_buffer(&mOggSyncState, READ_SIZE_BYTES);

					// Read bitstream from input file
					ssize_t bytesRead = (ssize_t)GetInputSource().Read(data, READ_SIZE_BYTES);
					if(-1 == bytesRead) {
						LOGGER_ERR("org.sbooth.AudioEngine.Decoder.OggSpeex", "Unable to read from the input file");
						break;
					}

					ogg_sync_wrote(&mOggSyncState, bytesRead);

					// No more data available from input file
					if(0 == bytesRead)
						break;
				}

				// Ensure all Ogg streams are read
				if(ogg_page_serialno(&mOggPage) != mOggStreamState.serialno)
					ogg_stream_reset_serialno(&mOggStreamState, ogg_page_serialno(&mOggPage));

				// Get the resultant Ogg page
				int result = ogg_stream_pagein(&mOggStreamState, &mOggPage);
				if(0 != result) {
					LOGGER_ERR("org.sbooth.AudioEngine.Decoder.OggSpeex", "Error reading Ogg page");
					break;
				}
			}
		}
	}

	mCurrentFrame += framesRead;

	if(0 == framesRead && mSpeexEOSReached)
		mTotalFrames = mCurrentFrame;

	return framesRead;
}
Exemple #25
0
int parse_ogg_stream(FILE *f,const char *pre_buffer,size_t pre_bytes,ogg_parser_funcs funcs,kate_uintptr_t data)
{
  char *ptr=NULL;
  ogg_sync_state oy;
  ogg_page og;
  ogg_int64_t bytes_read;
  static const size_t buffer_size=4096;
  size_t offset=0;
  int ret;
  long last_returned;
  long leftover_size=0;
  int in_hole=0;
  long first_hole_size=0;
  long hole_offset;

  ogg_sync_init(&oy);

  /* first add the buffer, if any */
  if (pre_buffer && pre_bytes) {
    ptr=ogg_sync_buffer(&oy,pre_bytes);
    if (!ptr) {
      fprintf(stderr,"Failed to get sync buffer for %lu bytes\n",(unsigned long)pre_bytes);
      goto error;
    }
    memcpy(ptr,pre_buffer,pre_bytes);
    ogg_sync_wrote(&oy,pre_bytes);
  }

  while (1) {
    ptr=ogg_sync_buffer(&oy,buffer_size);
    if (!ptr) {
      fprintf(stderr,"Failed to get sync buffer for %lu bytes\n",(unsigned long)buffer_size);
      goto error;
    }
    bytes_read=read(fileno(f),ptr,buffer_size);
    if (bytes_read==0) {
      break;
    }
    ogg_sync_wrote(&oy,bytes_read);

    last_returned=0;
    while ((ret=ogg_sync_pageout(&oy,&og))!=0) {
      if (ret>0) {
        /* new page */
        if (in_hole) {
          long hole_size=first_hole_size+leftover_size+oy.returned-(og.header_len+og.body_len);
          if (funcs.on_hole) {
            ret=(*funcs.on_hole)(data,hole_offset,hole_size);
            if (ret<0) goto error;
          }
          offset+=hole_size;
        }
        if (funcs.on_page) {
          ret=(*funcs.on_page)(data,offset,&og);
          if (ret<0) goto error;
        }
        in_hole=0;
        offset+=og.header_len+og.body_len;
      }
      else {
        /* hole in data */
        first_hole_size=oy.returned-last_returned;
        hole_offset=offset;
        in_hole=1;
      }
      leftover_size=0;
      last_returned=oy.returned;
    }
    leftover_size+=oy.fill-last_returned;
  }

  /* detect holes at end of file */
  if (leftover_size>0) {
    if (funcs.on_hole) {
      ret=(*funcs.on_hole)(data,offset,leftover_size);
      if (ret<0) goto error;
    }
  }

  ogg_sync_clear(&oy);
  return 0;

error:
  ogg_sync_clear(&oy);
  return -1;
}
bool SFB::Audio::OggSpeexDecoder::_Open(CFErrorRef *error)
{
	// Initialize Ogg data struct
	ogg_sync_init(&mOggSyncState);

	// Get the ogg buffer for writing
	char *data = ogg_sync_buffer(&mOggSyncState, READ_SIZE_BYTES);

	// Read bitstream from input file
	ssize_t bytesRead = (ssize_t)GetInputSource().Read(data, READ_SIZE_BYTES);
	if(-1 == bytesRead) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” could not be read."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Read error"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("Unable to read from the input file."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Tell the sync layer how many bytes were written to its internal buffer
	int result = ogg_sync_wrote(&mOggSyncState, bytesRead);
	if(-1 == result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Turn the data we wrote into an ogg page
	result = ogg_sync_pageout(&mOggSyncState, &mOggPage);
	if(1 != result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Initialize the stream and grab the serial number
	ogg_stream_init(&mOggStreamState, ogg_page_serialno(&mOggPage));

	// Get the first Ogg page
	result = ogg_stream_pagein(&mOggStreamState, &mOggPage);
	if(0 != result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Get the first packet (should be the header) from the page
	ogg_packet op;
	result = ogg_stream_packetout(&mOggStreamState, &op);
	if(1 != result) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	if(op.bytes >= 5 && !memcmp(op.packet, "Speex", 5))
		mSpeexSerialNumber = mOggStreamState.serialno;

	++mOggPacketCount;

	// Convert the packet to the Speex header
	SpeexHeader *header = speex_packet_to_header((char *)op.packet, (int)op.bytes);
	if(nullptr == header) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The file “%@” is not a valid Ogg Speex file."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Not an Ogg Speex file"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("The file's extension may not match the file's type."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::FileFormatNotRecognizedError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}
	else if(SPEEX_NB_MODES <= header->mode) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The Speex mode in the file “%@” is not supported."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file mode"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("This file may have been encoded with a newer version of Speex."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::FileFormatNotSupportedError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		speex_header_free(header);
		header = nullptr;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	const SpeexMode *mode = speex_lib_get_mode(header->mode);
	if(mode->bitstream_version != header->mode_bitstream_version) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("The Speex version in the file “%@” is not supported."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Unsupported Ogg Speex file version"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("This file was encoded with a different version of Speex."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::FileFormatNotSupportedError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		speex_header_free(header);
		header = nullptr;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	// Initialize the decoder
	mSpeexDecoder = speex_decoder_init(mode);
	if(nullptr== mSpeexDecoder) {
		if(error) {
			SFB::CFString description(CFCopyLocalizedString(CFSTR("Unable to initialize the Speex decoder."), ""));
			SFB::CFString failureReason(CFCopyLocalizedString(CFSTR("Error initializing Speex decoder"), ""));
			SFB::CFString recoverySuggestion(CFCopyLocalizedString(CFSTR("An unknown error occurred."), ""));

			*error = CreateErrorForURL(Decoder::ErrorDomain, Decoder::InputOutputError, description, mInputSource->GetURL(), failureReason, recoverySuggestion);
		}

		speex_header_free(header);
		header = nullptr;
		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	speex_decoder_ctl(mSpeexDecoder, SPEEX_SET_SAMPLING_RATE, &header->rate);

	mSpeexFramesPerOggPacket = (0 == header->frames_per_packet ? 1 : header->frames_per_packet);
	mExtraSpeexHeaderCount = (UInt32)header->extra_headers;

	// Initialize the speex bit-packing data structure
	speex_bits_init(&mSpeexBits);

	// Initialize the stereo mode
	mSpeexStereoState = speex_stereo_state_init();

	if(2 == header->nb_channels) {
		SpeexCallback callback;
		callback.callback_id = SPEEX_INBAND_STEREO;
		callback.func = speex_std_stereo_request_handler;
		callback.data = mSpeexStereoState;
		speex_decoder_ctl(mSpeexDecoder, SPEEX_SET_HANDLER, &callback);
	}

	// Canonical Core Audio format
	mFormat.mFormatID			= kAudioFormatLinearPCM;
	mFormat.mFormatFlags		= kAudioFormatFlagsNativeFloatPacked | kAudioFormatFlagIsNonInterleaved;

	mFormat.mBitsPerChannel		= 8 * sizeof(float);
	mFormat.mSampleRate			= header->rate;
	mFormat.mChannelsPerFrame	= (UInt32)header->nb_channels;

	mFormat.mBytesPerPacket		= (mFormat.mBitsPerChannel / 8);
	mFormat.mFramesPerPacket	= 1;
	mFormat.mBytesPerFrame		= mFormat.mBytesPerPacket * mFormat.mFramesPerPacket;

	mFormat.mReserved			= 0;

	// Set up the source format
	mSourceFormat.mFormatID				= 'SPEE';

	mSourceFormat.mSampleRate			= header->rate;
	mSourceFormat.mChannelsPerFrame		= (UInt32)header->nb_channels;

	switch(header->nb_channels) {
		case 1:		mChannelLayout = ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Mono);		break;
		case 2:		mChannelLayout = ChannelLayout::ChannelLayoutWithTag(kAudioChannelLayoutTag_Stereo);	break;
	}

	speex_header_free(header);
	header = nullptr;

	// Allocate the buffer list
	spx_int32_t speexFrameSize = 0;
	speex_decoder_ctl(mSpeexDecoder, SPEEX_GET_FRAME_SIZE, &speexFrameSize);

	if(!mBufferList.Allocate(mFormat, (UInt32)speexFrameSize)) {
		if(error)
			*error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainPOSIX, ENOMEM, nullptr);

		speex_stereo_state_destroy(mSpeexStereoState);
		mSpeexStereoState = nullptr;
		speex_decoder_destroy(mSpeexDecoder);
		mSpeexDecoder = nullptr;
		speex_bits_destroy(&mSpeexBits);

		ogg_sync_destroy(&mOggSyncState);
		return false;
	}

	for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i)
		mBufferList->mBuffers[i].mDataByteSize = 0;

	return true;
}
Exemple #27
0
static void
gst_tarkindec_chain (GstPad * pad, GstData * _data)
{
  GstBuffer *buf = GST_BUFFER (_data);
  TarkinDec *tarkindec;

  g_return_if_fail (pad != NULL);
  g_return_if_fail (GST_IS_PAD (pad));
  g_return_if_fail (buf != NULL);

  tarkindec = GST_TARKINDEC (gst_pad_get_parent (pad));

  if (!tarkindec->setup) {
    GST_ELEMENT_ERROR (tarkindec, CORE, NEGOTATION, (NULL),
        ("decoder not initialized (input is not tarkin?)"));
    if (GST_IS_BUFFER (buf))
      gst_buffer_unref (buf);
    else
      gst_pad_event_default (pad, GST_EVENT (buf));
    return;
  }

  if (GST_IS_EVENT (buf)) {
    switch (GST_EVENT_TYPE (buf)) {
      case GST_EVENT_EOS:
      default:
        gst_pad_event_default (pad, GST_EVENT (buf));
        break;
    }
  } else {
    gchar *data;
    gulong size;
    gchar *buffer;
    guchar *rgb;
    TarkinTime date;
    TarkinVideoLayerDesc *layer;

    /* data to decode */
    data = GST_BUFFER_DATA (buf);
    size = GST_BUFFER_SIZE (buf);

    buffer = ogg_sync_buffer (&tarkindec->oy, size);
    memcpy (buffer, data, size);
    ogg_sync_wrote (&tarkindec->oy, size);

    if (ogg_sync_pageout (&tarkindec->oy, &tarkindec->og)) {
      ogg_stream_pagein (&tarkindec->os, &tarkindec->og);

      while (ogg_stream_packetout (&tarkindec->os, &tarkindec->op)) {
        if (tarkindec->op.e_o_s)
          break;
        if (tarkindec->nheader < 3) {   /* 3 first packets to headerin */
          tarkin_synthesis_headerin (&tarkindec->ti, &tarkindec->tc,
              &tarkindec->op);

          if (tarkindec->nheader == 2) {
            tarkin_synthesis_init (tarkindec->tarkin_stream, &tarkindec->ti);
          }
          tarkindec->nheader++;
        } else {
          tarkin_synthesis_packetin (tarkindec->tarkin_stream, &tarkindec->op);

          while (tarkin_synthesis_frameout (tarkindec->tarkin_stream, &rgb, 0,
                  &date) == 0) {
            GstBuffer *outbuf;

            layer = &tarkindec->tarkin_stream->layer->desc;

            if (!GST_PAD_CAPS (tarkindec->srcpad)) {
              if (gst_pad_try_set_caps (tarkindec->srcpad, GST_CAPS_NEW ("tarkin_raw", "video/x-raw-rgb", "bpp", GST_PROPS_INT (24), "depth", GST_PROPS_INT (24), "endianness", GST_PROPS_INT (G_BYTE_ORDER), "red_mask", GST_PROPS_INT (0xff0000), "green_mask", GST_PROPS_INT (0xff00), "blue_mask", GST_PROPS_INT (0xff), "width", GST_PROPS_INT (layer->width), "height", GST_PROPS_INT (layer->height), "framerate", GST_PROPS_FLOAT (0.)  /* FIXME!!! */
                      )) <= 0) {
                GST_ELEMENT_ERROR (tarkindec, CORE, NEGOTATION, (NULL),
                    ("could not output format"));
                gst_buffer_unref (buf);
                return;
              }
            }
            outbuf = gst_buffer_new ();
            GST_BUFFER_DATA (outbuf) = rgb;
            GST_BUFFER_SIZE (outbuf) = layer->width * layer->height * 3;
            GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_DONTFREE);
            gst_pad_push (tarkindec->srcpad, GST_DATA (outbuf));

            tarkin_synthesis_freeframe (tarkindec->tarkin_stream, rgb);
          }
        }
      }
    }
    gst_buffer_unref (buf);
  }
}
Exemple #28
0
BOOL getogg_open(GETSND snd, UINT8 *ptr, UINT size) {

	__OV	*ov;
	char	*buffer;
	int		bytes;
	int 	i;
	int		result;

	snd->datptr = ptr;
	snd->datsize = size;

	ov = (__OV *)_MALLOC(sizeof(__OV), "__OV");
	if (ov == NULL) {
		goto ovopn_err0;
	}
	ZeroMemory(ov, sizeof(__OV));

	buffer = ogg_sync_buffer(&ov->oy, 4096);
	bytes = snd_read(snd, buffer, 4096);
	ogg_sync_wrote(&ov->oy, bytes);

	if (ogg_sync_pageout(&ov->oy, &ov->og) != 1) {
		TRACEOUT(("Input does not appear to be an Ogg bitstream."));
		goto ovopn_err1;
	}
	ogg_stream_init(&ov->os, ogg_page_serialno(&ov->og));

	vorbis_info_init(&ov->vi);
	vorbis_comment_init(&ov->vc);
	if (ogg_stream_pagein(&ov->os, &ov->og) < 0) {
		TRACEOUT(("Error reading first page of Ogg bitstream data."));
		goto ovopn_err1;
	}

	if (ogg_stream_packetout(&ov->os, &ov->op) != 1) {
		TRACEOUT(("Error reading initial header packet."));
		goto ovopn_err1;
	}

	if (vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op) < 0) {
		TRACEOUT(("This Ogg bitstream does not contain Vorbis audio data."));
		goto ovopn_err1;
	}

	i = 0;
	while(i < 2) {
		while(i < 2) {
			result = ogg_sync_pageout(&ov->oy, &ov->og);
			if (result == 0) {
				break;
			}
			if (result == 1) {
				ogg_stream_pagein(&ov->os, &ov->og);
				while(i < 2) {
					result = ogg_stream_packetout(&ov->os, &ov->op);
					if (result == 0) {
						break;
					}
					if (result < 0) {
						TRACEOUT(("Corrupt secondary header. Exiting."));
						goto ovopn_err1;
					}
					vorbis_synthesis_headerin(&ov->vi, &ov->vc, &ov->op);
					i++;
				}
			}
		}
		buffer = ogg_sync_buffer(&ov->oy, 4096);
		bytes = snd_read(snd, buffer, 4096);
		if ((bytes == 0) && (i < 2)) {
			TRACEOUT(("End of file before finding all Vorbis headers!"));
			return(-1);
		}
		ogg_sync_wrote(&ov->oy, bytes);
	}

	snd->snd = ov;
	snd->dec = (GSDEC)ogg_dec;
	snd->decend = ogg_decend;
	snd->samplingrate = ov->vi.rate;
	snd->channels = ov->vi.channels;
	snd->blocksize = 4096 * 2;
	snd->blocksamples = 4096 / ov->vi.channels;
	snd->bit = 16;

	vorbis_synthesis_init(&ov->vd, &ov->vi);
	vorbis_block_init(&ov->vd, &ov->vb);
	return(SUCCESS);

ovopn_err1:
	ogg_sync_clear(&ov->oy);
	_MFREE(ov);

ovopn_err0:
	return(FAILURE);
}
Exemple #29
0
static sf_count_t
ogg_read_sample (SF_PRIVATE *psf, void *ptr, sf_count_t lens, convert_func *transfn)
{
    VORBIS_PRIVATE *vdata = psf->codec_data ;
    OGG_PRIVATE *odata = psf->container_data ;
    int len, samples, i = 0 ;
    float **pcm ;

    len = lens / psf->sf.channels ;

    while ((samples = vorbis_synthesis_pcmout (&vdata->vd, &pcm)) > 0)
    {   if (samples > len) samples = len ;
        i += transfn (samples, ptr, i, psf->sf.channels, pcm) ;
        len -= samples ;
        /* tell libvorbis how many samples we actually consumed */
        vorbis_synthesis_read (&vdata->vd, samples) ;
        vdata->loc += samples ;
        if (len == 0)
            return i ; /* Is this necessary */
    }
    goto start0 ;		 /* Jump into the nasty nest */
    while (len > 0 && !odata->eos)
    {
        while (len > 0 && !odata->eos)
        {   int result = ogg_sync_pageout (&odata->oy, &odata->og) ;
            if (result == 0) break ; /* need more data */
            if (result < 0)
            {   /* missing or corrupt data at this page position */
                psf_log_printf (psf, "Corrupt or missing data in bitstream ; continuing...\n") ;
            }
            else
            {   /* can safely ignore errors at this point */
                ogg_stream_pagein (&odata->os, &odata->og) ;
start0:
                while (1)
                {   result = ogg_stream_packetout (&odata->os, &odata->op) ;
                    if (result == 0)
                        break ; /* need more data */
                    if (result < 0)
                    {   /* missing or corrupt data at this page position */
                        /* no reason to complain ; already complained above */
                    }
                    else
                    {   /* we have a packet.	Decode it */
                        if (vorbis_synthesis (&vdata->vb, &odata->op) == 0) /* test for success! */
                            vorbis_synthesis_blockin (&vdata->vd, &vdata->vb) ;
                        /*
                        **pcm is a multichannel float vector.	 In stereo, for
                        example, pcm [0] is left, and pcm [1] is right.	 samples is
                        the size of each channel.	 Convert the float values
                        (-1.<=range<=1.) to whatever PCM format and write it out */

                        while ((samples = vorbis_synthesis_pcmout (&vdata->vd, &pcm)) > 0)
                        {   if (samples>len) samples = len ;
                            i += transfn (samples, ptr, i, psf->sf.channels, pcm) ;
                            len -= samples ;
                            /* tell libvorbis how many samples we actually consumed */
                            vorbis_synthesis_read (&vdata->vd, samples) ;
                            vdata->loc += samples ;
                            if (len == 0)
                                return i ; /* Is this necessary */
                        } ;
                    }
                }
                if (ogg_page_eos (&odata->og)) odata->eos = 1 ;
            }
        }
        if (!odata->eos)
        {   char *buffer ;
            int bytes ;
            buffer = ogg_sync_buffer (&odata->oy, 4096) ;
            bytes = psf_fread (buffer, 1, 4096, psf) ;
            ogg_sync_wrote (&odata->oy, bytes) ;
            if (bytes == 0) odata->eos = 1 ;
        }
    }
    return i ;
} /* ogg_read_sample */
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for reading.
 * \param fd Descriptor that points to on disk storage of the OGG/Vorbis data.
 * \return The new filestream.
 */
static struct cw_filestream *ogg_vorbis_open(FILE *fp)
{
    int i;
    int bytes;
    int result;
    char **ptr;
    char *buffer;

    struct cw_filestream *tmp;

    if ((tmp = malloc(sizeof(struct cw_filestream))))
    {
        memset(tmp, 0, sizeof(struct cw_filestream));

        tmp->writing = 0;
        tmp->fp = fp;

        ogg_sync_init(&tmp->oy);

        buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
        bytes = fread(buffer, 1, BLOCK_SIZE, tmp->fp);

        ogg_sync_wrote(&tmp->oy, bytes);

        result = ogg_sync_pageout(&tmp->oy, &tmp->og);
        if (result != 1)
        {
            if (bytes < BLOCK_SIZE)
                cw_log(LOG_ERROR, "Run out of data... %d %s\n", errno, strerror(errno));
            else
                cw_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
            fclose(fp);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og));
        vorbis_info_init(&tmp->vi);
        vorbis_comment_init(&tmp->vc);

        if (ogg_stream_pagein(&tmp->os, &tmp->og) < 0)
        {
            cw_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        if (ogg_stream_packetout(&tmp->os, &tmp->op) != 1)
        { 
            cw_log(LOG_ERROR, "Error reading initial header packet.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        if (vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0)
        { 
            cw_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        i = 0;
        while (i < 2)
        {
            while (i < 2)
            {
                result = ogg_sync_pageout(&tmp->oy, &tmp->og);
                if (result == 0)
                    break;
                if (result == 1)
                {
                    ogg_stream_pagein(&tmp->os, &tmp->og);
                    while (i < 2)
                    {
                        result = ogg_stream_packetout(&tmp->os,&tmp->op);
                        if (result == 0)
                            break;
                        if (result < 0)
                        {
                            cw_log(LOG_ERROR, "Corrupt secondary header.  Exiting.\n");
                            fclose(fp);
                            ogg_stream_clear(&tmp->os);
                            vorbis_comment_clear(&tmp->vc);
                            vorbis_info_clear(&tmp->vi);
                            ogg_sync_clear(&tmp->oy);
                            free(tmp);
                            return NULL;
                        }
                        vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op);
                        i++;
                    }
                }
            }

            buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
            bytes = fread(buffer, 1, BLOCK_SIZE, tmp->fp);
            if (bytes == 0  &&  i < 2)
            {
                cw_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n");
                fclose(fp);
                ogg_stream_clear(&tmp->os);
                vorbis_comment_clear(&tmp->vc);
                vorbis_info_clear(&tmp->vi);
                ogg_sync_clear(&tmp->oy);
                free(tmp);
                return NULL;
            }
            ogg_sync_wrote(&tmp->oy, bytes);
        }
        
        ptr = tmp->vc.user_comments;
        while (*ptr)
        {
            cw_log(LOG_DEBUG, "OGG/Vorbis comment: %s\n", *ptr);
            ++ptr;
        }
        cw_log(LOG_DEBUG, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate);
        cw_log(LOG_DEBUG, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor);

        if (tmp->vi.channels != 1)
        {
            cw_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        

        if (tmp->vi.rate != 8000)
        {
            cw_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_block_clear(&tmp->vb);
            vorbis_dsp_clear(&tmp->vd);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        vorbis_synthesis_init(&tmp->vd, &tmp->vi);
        vorbis_block_init(&tmp->vd, &tmp->vb);

        if (cw_mutex_lock(&ogg_vorbis_lock))
        {
            cw_log(LOG_WARNING, "Unable to lock ogg_vorbis list\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_block_clear(&tmp->vb);
            vorbis_dsp_clear(&tmp->vd);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        glistcnt++;
        cw_mutex_unlock(&ogg_vorbis_lock);
        cw_update_use_count();
    }
    return tmp;
}