Added example code for encode/decode, continuing work on filling in
authorMonty <xiphmont@xiph.org>
Tue, 5 Oct 1999 15:35:02 +0000 (15:35 +0000)
committerMonty <xiphmont@xiph.org>
Tue, 5 Oct 1999 15:35:02 +0000 (15:35 +0000)
missing pieces of analysis/synthesis.

Monty

svn path=/trunk/vorbis/; revision=139

lib/Makefile.in
lib/analysis.c
lib/block.c
lib/codec.h
lib/decoder_example.c [new file with mode: 0644]
lib/encoder_example.c [new file with mode: 0644]
lib/info.c
lib/lpc.c
lib/synthesis.c

index 3b56998..96a046a 100644 (file)
@@ -1,6 +1,6 @@
 # vorbis makefile configured for use with gcc on any platform
 
-# $Id: Makefile.in,v 1.9 1999/10/02 21:21:18 xiphmont Exp $
+# $Id: Makefile.in,v 1.10 1999/10/05 15:34:56 xiphmont Exp $
 
 ###############################################################################
 #                                                                             #
@@ -27,19 +27,25 @@ AR=@AR@
 RANLIB=@RANLIB@
 LIBS=@LIBS@ -lm
 
-OFILES =       framing.o mdct.o smallft.o block.o envelope.o window.o\
+HFILES =       mdct.h codec.h bitwise.h envelope.h lpc.h lsp.h modes.h\
+               psy.h smallft.h window.h xlogmap.h
+
+LFILES =       framing.o mdct.o smallft.o block.o envelope.o window.o\
                lsp.o lpc.o analysis.o synthesis.o psy.o info.o bitwise.o
-TARGETFILES =  libvorbis.a
+
+EFILES =       encoder_example.o decoder_example.o
 
 all:
-       $(MAKE) target CFLAGS="$(OPT)" 
+       $(MAKE) target CFLAGS="$(OPT)"
 
-debug: 
+debug: 
        $(MAKE) target CFLAGS="$(DEBUG)"
 
 profile: 
        $(MAKE) target CFLAGS="$(PROFILE)"
 
+target:        libvorbis.a encoder_example decoder_example
+
 selftest:      
        $(MAKE) clean
        $(CC) $(DEBUG) $(LDFLAGS) -D_V_SELFTEST framing.c -o test_framing 
@@ -49,16 +55,19 @@ selftest:
        @./test_framing
        @./test_bitwise
 
-dsptest:       debug
-               $(CC) $(DEBUG) $(LDFLAGS) dsptest.c libvorbis.a -o dsptest -lm
+encoder_example:       $(EFILES) libvorbis.a
+       $(CC) $(CFLAGS) $(LDFLAGS) encoder_example.o libvorbis.a -o \
+                       encoder_example -lm
 
-target:        $(TARGETFILES)
+decoder_example:       $(EFILES) libvorbis.a
+       $(CC) $(CFLAGS) $(LDFLAGS) decoder_example.o libvorbis.a -o \
+                       decoder_example -lm
 
-libvorbis.a:   $(OFILES)       
-               $(AR) -r libvorbis.a $(OFILES)
+libvorbis.a:   $(LFILES)       
+               $(AR) -r libvorbis.a $(LFILES)
                $(RANLIB) libvorbis.a
 
-$(OFILES):     mdct.h
+$(LFILES):     $(HFILES)
 
 .c.o:
        $(CC) $(CFLAGS) -c $<
index b14515a..7f54a20 100644 (file)
@@ -14,7 +14,7 @@
  function: single-block PCM analysis
  author: Monty <xiphmont@mit.edu>
  modifications by: Monty
- last modification date: Oct 2 1999
+ last modification date: Oct 4 1999
 
  ********************************************************************/
 
 #include "mdct.h"
 #include "psy.h"
 
-extern void compute_balance(double *A, double *B, double *phi,int n);
+/* this code is still seriously abbreviated.  I'm filling in pieces as
+   we go... --Monty 19991004 */
 
 int vorbis_analysis(vorbis_block *vb,ogg_packet *op){
   int i;
-  double *window=vb->vd->window[vb->W][vb->lW][vb->nW];
-  lpc_lookup *vl=&vb->vd->vl[vb->W];
-  lpc_lookup *vbal=&vb->vd->vbal[vb->W];
-  int n=vb->pcmend;
-  static int frameno=0;
+  double           *window=vb->vd->window[vb->W][vb->lW][vb->nW];
+  lpc_lookup       *vl=&vb->vd->vl[vb->W];
+  vorbis_dsp_state *vd=vi->vd;
+  vorbis_info      *vi=vd->vi;
+  int              n=vb->pcmend;
 
-  double balance_v[vbal->m];
-  double balance_amp;
+  /*lpc_lookup       *vbal=&vb->vd->vbal[vb->W];
+    double balance_v[vbal->m];
+    double balance_amp;*/
 
+  /* we have the preecho metrics; decie what to do with them */
   _ve_envelope_sparsify(vb);
   _ve_envelope_apply(vb,0);
   
-  for(i=0;i<vb->pcm_channels;i++)
-    mdct_forward(&vb->vd->vm[vb->W],vb->pcm[i],vb->pcm[i],window);
+  for(i=0;i<vi->channels;i++)
+    mdct_forward(&vd->vm[vb->W],vb->pcm[i],vb->pcm[i],window);
 
 
-  /* hardwired to stereo for now */
-  {
+  /* no balance or channel coupling yet */
+  /*{
     double *C=vb->pcm[0];
     double *D=vb->pcm[1];
     
-    /* Balance */
-    
     balance_amp=_vp_balance_compute(D,C,balance_v,vbal);
     
-    /*{
+    {
       FILE *out;
       char buffer[80];
       
       sprintf(buffer,"com%d.m",frameno);
       out=fopen(buffer,"w+");
       for(i=0;i<n/2;i++){
-       fprintf(out," 0. 0.\n");
+        fprintf(out," 0. 0.\n");
        fprintf(out,"%g %g\n",C[i],D[i]);
        fprintf(out,"\n");
       }
@@ -83,13 +84,11 @@ int vorbis_analysis(vorbis_block *vb,ogg_packet *op){
       }
       fclose(out);
       
-      }*/
-    
-    /* apply balance vectors, mix down to the vectors we actually encode */
+    }
     
     _vp_balance_apply(D,C,balance_v,balance_amp,vbal,1);
-    
-    /*{
+      
+    {
       FILE *out;
       char buffer[80];
       
@@ -114,60 +113,45 @@ int vorbis_analysis(vorbis_block *vb,ogg_packet *op){
       }
       fclose(out);
       
-      }*/
-    
-    /* extract the spectral envelope and residue */
+    }
+  }*/
     
-    {
-      double floor1[n/2];
+  /* extract the spectral envelope and residue */
+  /* just do by channel.  No coupling yet */
+  {
+    for(i=0;i<vi->channels;vi++){
+      double floor[n/2];
       double curve[n/2];
-      double work[n/2];
-      double lpc1[80];
-      double lsp1[80];
-      double lsp2[80];
-      double amp1;
-      
-      memset(floor1,0,sizeof(floor1));
-      memset(work,0,sizeof(work));
-      
-      _vp_noise_floor(C,floor1,n/2);
-      _vp_noise_floor(D,floor1,n/2);
-      _vp_mask_floor(C,floor1,n/2);
-      _vp_mask_floor(D,floor1,n/2);
-    
-      memcpy(curve,floor1,sizeof(double)*n/2);
-      amp1=sqrt(vorbis_curve_to_lpc(curve,lpc1,vl));
-    
-      /*vorbis_lpc_to_lsp(lpc1,lsp1,30);
-      
-      {
-      int scale=1020;
-      int last=0;
-      for(i=0;i<30;i++){
-      double q=lsp1[i]/M_PI*scale;
-      int val=rint(q-last);
-      
-      last+=val;
-      lsp1[i]=val;
-      
-      }
-      }
+      double *lpc=vb->lpc[i];
+      double *lsp=vb->lsp[i];
+
+      memset(floor,0,sizeof(double)*n/2);
       
+      _vp_noise_floor(vb->pcm[i],floor,n/2);
+      _vp_mask_floor(vb->pcm[i],floor,n/2);
+      vb->amp[i]=sqrt(vorbis_curve_to_lpc(floor,lpc,vl));
+
+      vorbis_lpc_to_lsp(lpc,lsp,vl->m);
       
       {
-      int scale=1020;
-       double last=0;
-       for(i=0;i<30;i++){
-         last+=lsp1[i];
-         lsp2[i]=last*M_PI/scale;
+       /* make this scale configurable */
+       int scale=1020;
+       int last=0;
+       for(i=0;i<vl->m;i++){
+         double q=lsp[i]/M_PI*scale;
+         int val=rint(q-last);
+         
+         last+=val;
+         lsp[i]=val;
+         
        }
       }
+      
+      /* make residue.  Get the floor curve back from LPC (do we want
+         to recover all the way from LSP in the future?  Yes, once the
+         residue massaging is smarter) */
 
-
-
-      vorbis_lsp_to_lpc(lsp2,lpc1,30);*/
-
-      vorbis_lpc_to_curve(work,lpc1,amp1,vl);
+     vorbis_lpc_to_curve(work,lpc1,amp1,vl);
       
       _vp_psy_quantize(C,work,n/2);
       _vp_psy_quantize(D,work,n/2);
index 85b75ca..3dafdab 100644 (file)
@@ -31,6 +31,7 @@
 #include "window.h"
 #include "envelope.h"
 #include "mdct.h"
+#include "lpc.h"
 
 /* pcm accumulator examples (not exhaustive):
 
@@ -211,7 +212,7 @@ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
   return(0);
 }
 
-void vorbis_analysis_clear(vorbis_dsp_state *v){
+void vorbis_dsp_clear(vorbis_dsp_state *v){
   int i,j,k;
   if(v){
 
@@ -223,7 +224,7 @@ void vorbis_analysis_clear(vorbis_dsp_state *v){
       for(i=0;i<v->pcm_channels;i++)
        if(v->pcm[i])free(v->pcm[i]);
       free(v->pcm);
-      free(v->pcmret);
+      if(v->pcmret)free(v->pcmret);
     }
     if(v->multipliers){
       for(i=0;i<v->envelope_channels;i++)
@@ -233,6 +234,10 @@ void vorbis_analysis_clear(vorbis_dsp_state *v){
     _ve_envelope_clear(&v->ve);
     mdct_clear(&v->vm[0]);
     mdct_clear(&v->vm[1]);
+    lpc_clear(&v->vl[0]);
+    lpc_clear(&v->vl[1]);
+    lpc_clear(&v->vbal[0]);
+    lpc_clear(&v->vbal[1]);
     memset(v,0,sizeof(vorbis_dsp_state));
   }
 }
index 5470b22..cd34444 100644 (file)
  function: codec headers
  author: Monty <xiphmont@mit.edu>
  modifications by: Monty
- last modification date: Oct 2 1999
+ last modification date: Oct 4 1999
 
  ********************************************************************/
 
 #ifndef _vorbis_codec_h_
 #define _vorbis_codec_h_
 
+#include <sys/types.h> /* get BSD style 16/32/64 bit types */
+
+/* If we have defines from the configure script, use those */
+#ifdef size64
+#  define int64_t size64
+#endif
+#ifdef size32
+#  define int32_t size32
+#endif
+#ifdef size16
+#  define int16_t size16
+#endif
+
 /* lookup structures for various simple transforms *****************/
 
 typedef struct {
@@ -128,7 +141,7 @@ typedef struct {
 
 
   int    *lacing_vals;    /* The values that will go to the segment table */
-  size64 *pcm_vals;       /* pcm_pos values for headers. Not compact
+  int64_t *pcm_vals;      /* pcm_pos values for headers. Not compact
                             this way, but it is simple coupled to the
                             lacing fifo */
   long    lacing_storage;
@@ -145,7 +158,7 @@ typedef struct {
                             of a logical bitstream */
   long    serialno;
   long    pageno;
-  size64  pcmpos;
+  int64_t  pcmpos;
 
 } ogg_stream_state;
 
@@ -158,7 +171,7 @@ typedef struct {
   long  b_o_s;
   long  e_o_s;
 
-  size64 frameno;
+  int64_t frameno;
 
 } ogg_packet;
 
@@ -281,18 +294,20 @@ extern int    ogg_stream_reset(ogg_stream_state *os);
 extern int    ogg_stream_destroy(ogg_stream_state *os);
 extern int    ogg_stream_eof(ogg_stream_state *os);
 
-extern int    ogg_page_version(ogg_page *og);
-extern int    ogg_page_continued(ogg_page *og);
-extern int    ogg_page_bos(ogg_page *og);
-extern int    ogg_page_eos(ogg_page *og);
-extern size64 ogg_page_frameno(ogg_page *og);
-extern int    ogg_page_serialno(ogg_page *og);
-extern int    ogg_page_pageno(ogg_page *og);
+extern int     ogg_page_version(ogg_page *og);
+extern int     ogg_page_continued(ogg_page *og);
+extern int     ogg_page_bos(ogg_page *og);
+extern int     ogg_page_eos(ogg_page *og);
+extern int64_t ogg_page_frameno(ogg_page *og);
+extern int     ogg_page_serialno(ogg_page *og);
+extern int     ogg_page_pageno(ogg_page *og);
 
 /* Vorbis PRIMITIVES: general ***************************************/
 
+extern void vorbis_dsp_clear(vorbis_dsp_state *v);
+
 extern void vorbis_info_init(vorbis_info *vi); 
-extern int  vorbis_info_clear(vorbis_info *vi); 
+extern void vorbis_info_clear(vorbis_info *vi); 
 extern int  vorbis_info_modeset(vorbis_info *vi, int mode); 
 extern int  vorbis_info_addcomment(vorbis_info *vi, char *comment); 
 extern int  vorbis_info_headerin(vorbis_info *vi,ogg_packet *op);
@@ -306,7 +321,6 @@ extern int  vorbis_block_clear(vorbis_block *vb);
 
 /* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
 extern int      vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi);
-extern void     vorbis_analysis_clear(vorbis_dsp_state *v);
 
 extern double **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals);
 extern int      vorbis_analysis_wrote(vorbis_dsp_state *v,int vals);
@@ -314,7 +328,6 @@ extern int      vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb);
 extern int      vorbis_analysis(vorbis_block *vb,ogg_packet *op);
 
 /* Vorbis PRIMITIVES: synthesis layer *******************************/
-extern int  vorbis_synthesis_clear(vorbis_dsp_state *v);
 extern int  vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi);
 
 extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op);
diff --git a/lib/decoder_example.c b/lib/decoder_example.c
new file mode 100644 (file)
index 0000000..addfa18
--- /dev/null
@@ -0,0 +1,250 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
+ * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
+ * PLEASE READ THESE TERMS DISTRIBUTING.                            *
+ *                                                                  *
+ * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *
+ * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *
+ * http://www.xiph.org/                                             *
+ *                                                                  *
+ ********************************************************************
+
+ function: simple example decoder
+ author: Monty <xiphmont@mit.edu>
+ modifications by: Monty
+ last modification date: Oct 04 1999
+
+ ********************************************************************/
+
+/* Takes a vorbis bitstream from stdin and writes raw stereo PCM to
+   stdout */
+
+#include <stdio.h>
+#include <math.h>
+#include "codec.h"
+
+int16_t convbuffer[4096]; /* take 8k out of the data segment, not the stack */
+int convsize=4096;
+
+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_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;
+
+  /********** 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. */
+
+  /* submit a 4k block to libvorbis */
+  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){
+    /* 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 */
+  
+  /* 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==-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++;
+       }
+      }
+    }
+    /* 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;
+    }
+    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;
+
+  /* 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==-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 out=(samples<convsize?samples:convsize);
+             
+             /* convert doubles to 16 bit signed ints (host order) and
+                interleave */
+             for(i=0;i<vi.channels;i++){
+               int16_t *ptr=convbuffer+i;
+               double  *mono=pcm[i];
+               for(j=0;j<out;j++){
+                 int val=rint(mono[j]*32767.);
+                 /* might as well guard clipping */
+                 if(val>32767)val=32767;
+                 if(val<-32768)val=-32768;
+                 *ptr=val;
+                 ptr+=2;
+               }
+             }
+             
+             vorbis_synthesis_read(&vd,out); /* 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,stdin);
+      if(bytes==0)eos=1;
+    }else
+      ogg_sync_wrote(&oy,bytes);
+  }
+  
+  /* clean up and exit (this example doesn't deal with the possibility
+     of chaining logical streams */
+  
+  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_info_clear(&vi);
+  vorbis_dsp_clear(&vd);
+  vorbis_block_clear(&vb);
+  
+  fprintf(stderr,"Done.\n");
+  return(0);
+}
+
diff --git a/lib/encoder_example.c b/lib/encoder_example.c
new file mode 100644 (file)
index 0000000..e8b00e0
--- /dev/null
@@ -0,0 +1,156 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
+ * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
+ * PLEASE READ THESE TERMS DISTRIBUTING.                            *
+ *                                                                  *
+ * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *
+ * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *
+ * http://www.xiph.org/                                             *
+ *                                                                  *
+ ********************************************************************
+
+ function: simple example encoder
+ author: Monty <xiphmont@mit.edu>
+ modifications by: Monty
+ last modification date: Oct 04 1999
+
+ ********************************************************************/
+
+/* takes a stereo 16bit 44.1kHz WAV file from stdin and encodes it into
+   a Vorbis bitstream */
+
+#include <stdio.h>
+#include <math.h>
+#include "codec.h"
+
+#define READ 1024
+signed char readbuffer[READ*4+44]; /* out of the data segment, not the stack */
+
+int main(){
+  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 */
+
+  int eos=0;
+
+  /* we cheat on the WAV header; we just bypass 44 bytes and never
+     verify that it matches 16bit/stereo/44.1kHz.  This is just an
+     example, after all. */
+
+  fread(readbuffer,1,44,stdin);
+
+  /********** Encode setup ************/
+
+  /* choose an encoding mode */
+  /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
+  vorbis_info_modeset(&vi,0); 
+
+  /* add a comment */
+  vorbis_info_addcomment(&vi,"Track encoded by encoder_example.c");
+
+  /* set up the analysis state and auxiliary encoding storage */
+  vorbis_analysis_init(&vd,&vi);
+  vorbis_block_init(&vd,&vb);
+  
+  /* set up our packet->stream encoder */
+  ogg_stream_init(&os,0); /* serial number 0 is fine */
+
+  /* Vorbis streams begin with three headers; the initial header (with
+     most of the codec setup parameters) which is mandated by the Ogg
+     bitstream spec.  The second header holds any comment fields.  The
+     third header holds the bitstream codebook.  We merely need to
+     make the headers, then pass them to libvorbis one at a time;
+     libvorbis handles the additional Ogg bitstream constraints */
+
+  {
+    ogg_packet header;
+    ogg_packet header_comm;
+    ogg_packet header_code;
+
+    vorbis_info_headerout(&vi,&header,&header_comm,&header_code);
+    ogg_stream_packetin(&os,&header); /* automatically placed in its own
+                                        page */
+    ogg_stream_packetin(&os,&header_comm);
+    ogg_stream_packetin(&os,&header_code);
+
+    /* no need to write out here.  We'll get to that in the main loop */
+  }
+  
+  while(!eos){
+    long i;
+    long bytes=fread(readbuffer,1,READ*4,stdin); /* stereo hardwired here */
+
+    if(bytes==0){
+      /* end of file.  this can be done implicitly in the mainline,
+         but it's easier to see here in non-clever fashion.
+         Tell the library we're at end of stream so that it can handle
+         the last frame and mark end of stream in the output properly */
+      vorbis_analysis_wrote(&vd,0);
+
+    }else{
+      /* data to encode */
+
+      /* expose the buffer to submit data */
+      double **buffer=vorbis_analysis_buffer(&vd,READ);
+      
+      /* uninterleave samples */
+      for(i=0;i<bytes/4;i++){
+       buffer[0][i]=((readbuffer[i*4+1]<<8)|
+                     (0x00ff&(int)readbuffer[i*4]))/32768.;
+       buffer[1][i]=((readbuffer[i*4+3]<<8)|
+                     (0x00ff&(int)readbuffer[i*4+2]))/32768.;
+      }
+    
+      /* tell the library how much we actually submitted */
+      vorbis_analysis_wrote(&vd,i);
+    }
+
+    /* vorbis does some data preanalysis, then divvies up blocks for
+       more involved (potentially parallel) processing.  Get a single
+       block for encoding now */
+    while(vorbis_analysis_blockout(&vd,&vb)==1){
+
+      /* analysis */
+      vorbis_analysis(&vb,&op);
+
+      /* weld the packet into the bitstream */
+      ogg_stream_packetin(&os,&op);
+
+      /* write out pages (if any) */
+      while(!eos){
+       int result=ogg_stream_pageout(&os,&og);
+       if(result==0)break;
+       fwrite(og.header,1,og.header_len,stdout);
+       fwrite(og.body,1,og.body_len,stdout);
+
+       /* this could be set above, but for illustrative purposes, I do
+          it here (to show that vorbis does know where the stream ends) */
+       
+       if(ogg_page_eos(&og))eos=1;
+
+      }
+    }
+  }
+
+  /* clean up and exit */
+  
+  ogg_stream_clear(&os);
+  vorbis_info_clear(&vi);
+  vorbis_dsp_clear(&vd);
+  vorbis_block_clear(&vb);
+  
+  /* ogg_page and ogg_packet structs always point to storage in
+     libvorbis.  They're never freed or manipulated directly */
+  
+  fprintf(stderr,"Done.\n");
+  return(0);
+}
+
index e8b96bb..5dc6d53 100644 (file)
@@ -44,7 +44,7 @@ int vorbis_info_modeset(vorbis_info *vi, int mode){
 }
 
 /* convenience function */
-int vorbis_info_add_comment(vorbis_info *vi,char *comment){
+int vorbis_info_addcomment(vorbis_info *vi,char *comment){
   vi->user_comments=realloc(vi->user_comments,
                            (vi->comments+1)*sizeof(char *));
   vi->user_comments[vi->comments]=strdup(comment);
@@ -81,7 +81,6 @@ int vorbis_info_headerin(vorbis_info *vi,ogg_packet *op){
     /* Also verify header-ness, vorbis */
     {
       char buffer[6];
-      int type;
       memset(buffer,0,6);
       _v_readstring(&opb,buffer,6);
       if(memcmp(buffer,"vorbis",6)){
@@ -193,6 +192,7 @@ int vorbis_info_headerout(vorbis_info *vi,
 
   /* build the packet */
   if(vi->header)free(vi->header);
+  vi->header=malloc(_oggpack_bytes(&opb));
   memcpy(vi->header,opb.buffer,_oggpack_bytes(&opb));
   op->packet=vi->header;
   op->bytes=_oggpack_bytes(&opb);
@@ -238,6 +238,7 @@ int vorbis_info_headerout(vorbis_info *vi,
   }
   
   if(vi->header1)free(vi->header1);
+  vi->header1=malloc(_oggpack_bytes(&opb));
   memcpy(vi->header1,opb.buffer,_oggpack_bytes(&opb));
   op_comm->packet=vi->header1;
   op_comm->bytes=_oggpack_bytes(&opb);
@@ -255,6 +256,7 @@ int vorbis_info_headerout(vorbis_info *vi,
   _oggpack_write(&opb,0x02,8);
 
   if(vi->header2)free(vi->header2);
+  vi->header2=malloc(_oggpack_bytes(&opb));
   memcpy(vi->header2,opb.buffer,_oggpack_bytes(&opb));
   op_code->packet=vi->header2;
   op_code->bytes=_oggpack_bytes(&opb);
@@ -267,7 +269,7 @@ int vorbis_info_headerout(vorbis_info *vi,
   return(0);
 }
 
-int vorbis_info_clear(vorbis_info *vi){
+void vorbis_info_clear(vorbis_info *vi){
   /* clear the non-flat storage before zeroing */
 
   /* comments */
index b9af103..4010ca8 100644 (file)
--- a/lib/lpc.c
+++ b/lib/lpc.c
@@ -265,8 +265,6 @@ double vorbis_curve_to_lpc(double *curve,double *lpc,lpc_lookup *l){
 
   }
 
-  memcpy(curve,work,sizeof(work));
-
   return vorbis_gen_lpc(work,lpc,l);
 }
 
index 89136e2..aa5d927 100644 (file)
@@ -33,6 +33,21 @@ int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){
   /* get the LSP params back to LPC params. This will be for each
      spectral floor curve */
 
+      
+  /*      {
+      int scale=1020;
+       double last=0;
+       for(i=0;i<30;i++){
+         last+=lsp1[i];
+         lsp2[i]=last*M_PI/scale;
+       }
+      }
+
+
+
+      vorbis_lsp_to_lpc(lsp2,lpc1,30);*/
+
+
   /*for(i=0;i<vi->floorch;i++)
     vorbis_lsp_to_lpc(vb->lsp[i],vb->lpc[i],vi->floororder);*/