From 3125d16e218e49a0d17f876767fecfd30d6306d7 Mon Sep 17 00:00:00 2001 From: Monty Date: Sat, 30 Oct 1999 06:39:10 +0000 Subject: [PATCH] Fixed mdct bug (error in init created invalid bitreverse lookup) Modify example decoder to handle chained bitstreams Modify example encoder to choose random serialno. Monty svn path=/trunk/vorbis/; revision=156 --- lib/chaining_example.c | 46 +++++- lib/decoder_example.c | 393 +++++++++++++++++++++++++------------------------ lib/encoder_example.c | 9 +- lib/mdct.c | 7 +- 4 files changed, 254 insertions(+), 201 deletions(-) diff --git a/lib/chaining_example.c b/lib/chaining_example.c index 0c1e95b..3f3f95f 100644 --- a/lib/chaining_example.c +++ b/lib/chaining_example.c @@ -43,7 +43,47 @@ /* There are also different ways to implement seeking. Enough information exists in an Ogg bitstream to seek to sample-granularity positions in the output. Or, one can seek by - picking some portion of the stream roughtly in the area we only - want course navigation through the stream. This example implements - the latter. */ + picking some portion of the stream roughtly in the area if we only + want course navigation through the stream. */ + +typedef struct { + + + + +} Vorbis_File; + +typedef struct { + 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_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; + int i; + int eos=0; + + + + +} Vorbis_Decode; + + +int vorbis_open_file(FILE *f,Vorbis_File *vf){ + + +} + +int vorbis_clear_file(Vorbis_File *vf){ + + + +} diff --git a/lib/decoder_example.c b/lib/decoder_example.c index 05c4198..e2313bd 100644 --- a/lib/decoder_example.c +++ b/lib/decoder_example.c @@ -14,12 +14,14 @@ function: simple example decoder author: Monty modifications by: Monty - last modification date: Oct 04 1999 + last modification date: Oct 29 1999 ********************************************************************/ /* Takes a vorbis bitstream from stdin and writes raw stereo PCM to - stdout */ + stdout. Decodes simple and chained OggVorbis files from beginning to + end. +*/ #include #include @@ -42,220 +44,229 @@ int main(){ char *buffer; int bytes; - int i; - int eos=0; /********** Decode setup ************/ ogg_sync_init(&oy); /* Now we can read pages */ - /* 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. */ + while(1){ /* we repeat if the bitstream is chained */ + int eos=0; + int i; - /* submit a 4k block to libvorbis */ - buffer=ogg_sync_buffer(&oy,4096); - bytes=fread(buffer,1,4096,stdin); - ogg_sync_wrote(&oy,bytes); + /* 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. */ - /* Get the first page. */ - if(ogg_sync_pageout(&oy,&og)!=1){ - /* 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); - 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_info_headerin(&vi,&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 */ + /* submit a 4k block to libvorbis' Ogg layer */ + buffer=ogg_sync_buffer(&oy,4096); + bytes=fread(buffer,1,4096,stdin); + 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); + } - /* 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){ + /* 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); + 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_info_headerin(&vi,&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){ - 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==-1){ - /* 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); + 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==-1){ + /* 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_info_headerin(&vi,&op); + i++; } - vorbis_info_headerin(&vi,&op); - i++; } } + /* no harm in not checking before adding more */ + buffer=ogg_sync_buffer(&oy,4096); + bytes=fread(buffer,1,4096,stdin); + if(bytes==0){ + fprintf(stderr,"End of file before finding all Vorbis headers!\n"); + exit(1); + } + ogg_sync_wrote(&oy,bytes); } - /* no harm in not checking before adding more */ - buffer=ogg_sync_buffer(&oy,4096); - bytes=fread(buffer,1,4096,stdin); - if(bytes==0){ - 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=vi.user_comments; - while(*ptr){ - fprintf(stderr,"%s\n",*ptr); - ++ptr; + + /* Throw the comments plus a few lines about the bitstream we're + decoding */ + { + char **ptr=vi.user_comments; + while(*ptr){ + fprintf(stderr,"%s\n",*ptr); + ++ptr; + } + fprintf(stderr,"\nBitstream is %d channel, %dHz\n",vi.channels,vi.rate); + fprintf(stderr,"Encoded by: %s\n\n",vi.vendor); } - fprintf(stderr,"\nBitstream is %d channel, %dHz\n",vi.channels,vi.rate); - fprintf(stderr,"Encoded by: %s\n\n",vi.vendor); - } - - convsize=4096/vi.channels; + + 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){ + /* 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){ - int result=ogg_sync_pageout(&oy,&og); - if(result==0)break; /* need more data */ - if(result==-1){ /* 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==-1){ /* missing or corrupt data at this page position */ - /* no reason to complain; already complained above */ - }else{ - /* we have a packet. Decode it */ - double **pcm; - int samples; - - vorbis_synthesis(&vb,&op); - vorbis_synthesis_blockin(&vd,&vb); - /* - - **pcm is a multichannel double 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 out=(samples32767){ - val=32767; - clipflag=1; - } - if(val<-32768){ - val=-32768; - clipflag=1; + vorbis_synthesis(&vb,&op); + vorbis_synthesis_blockin(&vd,&vb); + /* + + **pcm is a multichannel double 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 out=(samples32767){ + val=32767; + clipflag=1; + } + if(val<-32768){ + val=-32768; + clipflag=1; + } + *ptr=val; + ptr+=2; } - *ptr=val; - ptr+=2; } - } - - if(clipflag) - fprintf(stderr,"Clipping in frame %ld\n",vd.sequence); - - - fwrite(convbuffer,2*vi.channels,out,stdout); - - vorbis_synthesis_read(&vd,out); /* tell libvorbis how - many samples we - actually consumed */ - } + + if(clipflag) + fprintf(stderr,"Clipping in frame %ld\n",vd.sequence); + + + fwrite(convbuffer,2*vi.channels,out,stdout); + + vorbis_synthesis_read(&vd,out); /* tell libvorbis how + many samples we + actually consumed */ + } + } } + if(ogg_page_eos(&og))eos=1; } - if(ogg_page_eos(&og))eos=1; + } + if(!eos){ + buffer=ogg_sync_buffer(&oy,4096); + bytes=fread(buffer,1,4096,stdin); + ogg_sync_wrote(&oy,bytes); + if(bytes==0)eos=1; } } - if(!eos){ - buffer=ogg_sync_buffer(&oy,4096); - bytes=fread(buffer,1,4096,stdin); - ogg_sync_wrote(&oy,bytes); - if(bytes==0)eos=1; - } - } - - /* clean up and exit (this example doesn't deal with the possibility - of chaining logical streams */ + + /* 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_dsp_clear(&vd); + vorbis_block_clear(&vb); + vorbis_info_clear(&vi); /* must be called last */ + } + + /* OK, clean up the framer */ ogg_sync_clear(&oy); - ogg_stream_clear(&os); - - /* ogg_page and ogg_packet structs always point to storage in - libvorbis. They're never freed or manipulated directly */ - - vorbis_dsp_clear(&vd); - vorbis_block_clear(&vb); - vorbis_info_clear(&vi); /* must be called last */ fprintf(stderr,"Done.\n"); return(0); diff --git a/lib/encoder_example.c b/lib/encoder_example.c index 66e9e86..ff21b90 100644 --- a/lib/encoder_example.c +++ b/lib/encoder_example.c @@ -14,7 +14,7 @@ function: simple example encoder author: Monty modifications by: Monty - last modification date: Oct 04 1999 + last modification date: Oct 29 1999 ********************************************************************/ @@ -22,6 +22,8 @@ a Vorbis bitstream */ #include +#include +#include #include #include "codec.h" @@ -61,7 +63,10 @@ int main(){ vorbis_block_init(&vd,&vb); /* set up our packet->stream encoder */ - ogg_stream_init(&os,0); /* serial number 0 is fine */ + /* pick a random serial number; that way we can more likely build + chained streams just by concatenation */ + srandom(time(NULL)); + ogg_stream_init(&os,random()); /* Vorbis streams begin with three headers; the initial header (with most of the codec setup parameters) which is mandated by the Ogg diff --git a/lib/mdct.c b/lib/mdct.c index 7bb9ad7..ba59db7 100644 --- a/lib/mdct.c +++ b/lib/mdct.c @@ -55,9 +55,6 @@ void mdct_init(mdct_lookup *lookup,int n){ double *CE=BE+n/2; double *CO=CE+1; - int *bitA=bitrev; - int *bitB=bitrev+1; - int i; int log2n=lookup->log2n=rint(log(n)/log(2)); lookup->n=n; @@ -86,8 +83,8 @@ void mdct_init(mdct_lookup *lookup,int n){ int acc=0; for(j=0;msb>>j;j++) if((msb>>j)&i)acc|=1<