First functional block sizing and seperation code (analysis)
authorMonty <xiphmont@xiph.org>
Wed, 28 Jul 1999 09:07:47 +0000 (09:07 +0000)
committerMonty <xiphmont@xiph.org>
Wed, 28 Jul 1999 09:07:47 +0000 (09:07 +0000)
Monty 19990728

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

lib/Makefile.in
lib/analysis.c
lib/envelope.h [new file with mode: 0644]
lib/window.c [new file with mode: 0644]
lib/window.h [new file with mode: 0644]

index 3dfc7551834d53a612dc0bb08cef3332ae63dda5..b7c41d9a0b50d237fef5429d5e866d9af3b90d50 100644 (file)
@@ -1,6 +1,6 @@
 # vorbis makefile configured for use with gcc on any platform
 
-# $Id: Makefile.in,v 1.2 1999/07/27 08:44:52 xiphmont Exp $
+# $Id: Makefile.in,v 1.3 1999/07/28 09:07:45 xiphmont Exp $
 
 ###############################################################################
 #                                                                             #
@@ -42,7 +42,9 @@ profile:
 selftest:
        $(MAKE) clean
        $(CC) $(DEBUG) $(LDFLAGS) -D_V_SELFTEST framing.c -o test_framing 
-       $(CC) $(DEBUG) $(LDFLAGS) -D_V_SELFTEST analysis.c -o test_blocking
+       $(CC) $(DEBUG) -c window.c
+       $(CC) $(DEBUG) $(LDFLAGS) -D_V_SELFTEST analysis.c window.o\
+               -o test_blocking -lm
        @echo
        @./test_framing
        @./test_blocking
index f8903b76b1707e1873901bcf53a9fc1adb6a919c..c8430813a2ef48548f38b1b31c33a9d8d7786ce9 100644 (file)
@@ -29,6 +29,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include "codec.h"
+#include "window.h"
+#include "envelope.h"
 
 /* pcm accumulator and multipliers 
    examples (not exhaustive):
@@ -79,16 +81,20 @@ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
   v->block_size[0]=512; 
   v->block_size[1]=2048;
   
-  /*  v->window[0][0][0]=vorbis_window(v->block_size[0],
+  v->window[0][0][0]=_vorbis_window(v->block_size[0],
                                   v->block_size[0]/2,v->block_size[0]/2);
-  v->window[1][0][0]=vorbis_window(v->block_size[1],
+  v->window[0][0][1]=v->window[0][0][0];
+  v->window[0][1][0]=v->window[0][0][0];
+  v->window[0][1][1]=v->window[0][0][0];
+
+  v->window[1][0][0]=_vorbis_window(v->block_size[1],
                                   v->block_size[0]/2,v->block_size[0]/2);
-  v->window[1][0][1]=vorbis_window(v->block_size[1],
+  v->window[1][0][1]=_vorbis_window(v->block_size[1],
                                   v->block_size[0]/2,v->block_size[1]/2);
-  v->window[1][1][0]=vorbis_window(v->block_size[1],
+  v->window[1][1][0]=_vorbis_window(v->block_size[1],
                                   v->block_size[1]/2,v->block_size[0]/2);
-  v->window[1][1][1]=vorbis_window(v->block_size[1],
-  v->block_size[1]/2,v->block_size[1]/2);*/
+  v->window[1][1][1]=_vorbis_window(v->block_size[1],
+                                   v->block_size[1]/2,v->block_size[1]/2);
 
   /* initialize the storage vectors to a decent size greater than the
      minimum */
@@ -135,10 +141,11 @@ int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
 void vorbis_analysis_clear(vorbis_dsp_state *v){
   int i,j,k;
   if(v){
-    for(i=0;i<2;i++)
-      for(j=0;j<2;j++)
-       for(k=0;k<2;k++)
-         if(v->window[i][j][k])free(v->window[i][j][k]);
+
+    if(v->window[0][0][0])free(v->window[0][0][0]);
+    for(j=0;j<2;j++)
+      for(k=0;k<2;k++)
+       if(v->window[1][j][k])free(v->window[1][j][k]);
     if(v->pcm){
       for(i=0;i<v->pcm_channels;i++)
        if(v->pcm[i])free(v->pcm[i]);
@@ -159,16 +166,8 @@ void vorbis_analysis_clear(vorbis_dsp_state *v){
   }
 }
 
-/* call with val==0 to set eof */
 double **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){
   int i;
-  if(vals<=0){
-    /* We're encoding the end of the stream.  Just make sure we have
-       [at least] a full block of zeroes at the end. */
-    v->eofflag=v->pcm_current;
-    v->pcm_current+=v->block_size[1]*2;
-    vals=0;
-  }
 
   /* Do we have enough storage space for the requested buffer? If not,
      expand the PCM (and envelope) storage */
@@ -186,26 +185,33 @@ double **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){
     }
   }
 
-  if(vals<=0){
-    /* We're encoding the end of the stream.  Just make sure we have
-       [at least] a full block of zeroes at the end. */
-    
-    for(i=0;i<v->pcm_channels;i++)
-      memset(v->pcm[i]+v->eofflag,0,
-            (v->pcm_current-v->eofflag)*sizeof(double));
-  }
-
   for(i=0;i<v->pcm_channels;i++)
     v->pcmret[i]=v->pcm[i]+v->pcm_current;
     
   return(v->pcmret);
 }
 
+/* call with val<=0 to set eof */
+
 int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){
-  if(v->pcm_current+vals>v->pcm_storage)
-    return(-1);
+  if(vals<=0){
+    /* We're encoding the end of the stream.  Just make sure we have
+       [at least] a full block of zeroes at the end. */
+
+    int i;
+    vorbis_analysis_buffer(v,v->block_size[1]*2);
+    v->eofflag=v->pcm_current;
+    v->pcm_current+=v->block_size[1]*2;
+    for(i=0;i<v->pcm_channels;i++)
+      memset(v->pcm[i]+v->eofflag,0,
+            (v->pcm_current-v->eofflag)*sizeof(double));
+  }else{
+    
+    if(v->pcm_current+vals>v->pcm_storage)
+      return(-1);
 
-  v->pcm_current+=vals;
+    v->pcm_current+=vals;
+  }
   return(0);
 }
 
@@ -245,7 +251,7 @@ int vorbis_block_clear(vorbis_block *vb){
 /* do the deltas, envelope shaping, pre-echo and determine the size of
    the next block on which to continue analysis */
 int vorbis_analysis_block(vorbis_dsp_state *v,vorbis_block *vb){
-  int i;
+  int i,j;
   long beginW=v->centerW-v->block_size[v->W]/2,centerNext;
   long beginM=beginW/v->samples_per_envelope_step;
 
@@ -276,9 +282,13 @@ int vorbis_analysis_block(vorbis_dsp_state *v,vorbis_block *vb){
     i=v->centerW;
   i/=v->samples_per_envelope_step;
 
-  for(;i<v->envelope_storage;i++)if(v->multipliers[i])break;
+  for(;i<v->envelope_current;i++){
+    for(j=0;j<v->envelope_channels;j++)
+      if(v->multipliers[j][i])break;
+    if(j<v->envelope_channels)break;
+  }
   
-  if(i<v->envelope_storage){
+  if(i<v->envelope_current){
     /* Ooo, we hit a multiplier. Is it beyond the boundary to make the
        upcoming block large ? */
     long largebound;
@@ -305,6 +315,8 @@ int vorbis_analysis_block(vorbis_dsp_state *v,vorbis_block *vb){
      know the size of the next block for sure and we need that now to
      figure out the window shape of this block */
   
+  centerNext=v->centerW+v->block_size[v->W]/4+v->block_size[v->nW]/4;
+
   {
     long blockbound=centerNext+v->block_size[v->nW]/2;
     if(v->pcm_current<blockbound)return(0); /* not enough data yet */    
@@ -344,8 +356,7 @@ int vorbis_analysis_block(vorbis_dsp_state *v,vorbis_block *vb){
                            eof<0  'no more to do'; doesn't get here */
 
   if(v->eofflag){
-    long endW=beginW+v->block_size[v->W];
-    if(endW>=v->eofflag){
+    if(v->centerW>=v->eofflag){
       v->eofflag=-1;
       vb->eofflag=1;
     }
@@ -377,6 +388,9 @@ int vorbis_analysis_block(vorbis_dsp_state *v,vorbis_block *vb){
 
     v->frame++;
     v->samples+=movementW;
+
+    if(v->eofflag)
+      v->eofflag-=movementW;
   }
 
   /* done */
@@ -413,4 +427,94 @@ int vorbis_analysis_packetout(vorbis_dsp_state *v, vorbis_block *vb,
 
 
 
+#ifdef _V_SELFTEST
+#include <stdio.h>
+#include <math.h>
+
+void _va_envelope_deltas(vorbis_dsp_state *v){
+  /* do nothing... */
+}
+
+void _va_envelope_multipliers(vorbis_dsp_state *v){
+  /* set 'random' deltas... */
+  int new_current=v->pcm_current/v->samples_per_envelope_step;
+  int i,j;
+
+  for(i=v->envelope_current;i<new_current;i++){
+    int flag=0;
+    for(j=0;j<v->samples_per_envelope_step;j++)
+      if(v->pcm[0][j+i*v->samples_per_envelope_step]>5)flag=1;
+    
+    for(j=0;j<v->envelope_channels;j++)
+      v->multipliers[j][i]=flag;
+  }
+  v->envelope_current=i;
+}
+
+
+/* basic test of PCM blocking:
+
+   construct a PCM vector and block it using preset sizing in our fake
+   delta/multiplier generation.  Immediately hand the block over to
+   'synthesis' and rebuild it. */
+
+int main(){
+  int blocksize=1024;
+  int fini=5000*1024;
+  vorbis_dsp_state encode,decode;
+  vorbis_info vi;
+  vorbis_block vb;
+  long counterin=0;
+  long counterout=0;
+  int done=0;
+  char *temp[]={ "Test" ,"the Test band", "test records",NULL };
+
+  vi.channels=2;
+  vi.rate=44100;
+  vi.version=0;
+  vi.mode=0;
+
+  vi.user_comments=temp;
+  vi.vendor="Xiphophorus";
+
+  vorbis_analysis_init(&encode,&vi);
+
+  memset(&vb,0,sizeof(vorbis_block));
+  vorbis_block_init(&encode,&vb);
+
+  /* Submit 100K samples of data reading out blocks... */
+  
+  while(!done){
+    int i;
+    double **buf=vorbis_analysis_buffer(&encode,blocksize);
+    for(i=0;i<blocksize;i++){
+      buf[0][i]=1;
+      buf[1][i]=-1;
+
+      if((counterin+i)%15000>13000)buf[0][i]+=10;
+    }
+
+    i=(counterin+blocksize>fini?fini-counterin:blocksize);
+    vorbis_analysis_wrote(&encode,i);
+    counterin+=i;
+
+    while(vorbis_analysis_block(&encode,&vb)){
+      double *window=encode.window[vb.W][vb.lW][vb.nW];
+      FILE *out;
+      char path[80];
+      int begin=counterout-encode.block_size[vb.W]/2;
+
+      if(vb.eofflag){
+       done=1;
+       break;
+      }
+
+      counterout=counterout+encode.block_size[vb.W]/4+
+       encode.block_size[vb.nW]/4;
+
+    }
+  }
+  return 0;
+}
 
+#endif
diff --git a/lib/envelope.h b/lib/envelope.h
new file mode 100644 (file)
index 0000000..c9b0283
--- /dev/null
@@ -0,0 +1,28 @@
+/********************************************************************
+ *                                                                  *
+ * 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: PCM data envelope analysis and manipulation
+ author: Monty <xiphmont@mit.edu>
+ modifications by: Monty
+ last modification date: Jul 27 1999
+
+ ********************************************************************/
+
+#ifndef _V_ENVELOPE_
+#define _V_ENVELOPE_
+
+extern void _va_envelope_deltas(vorbis_dsp_state *v);
+extern void _va_envelope_multipliers(vorbis_dsp_state *v);
+
+#endif
+
diff --git a/lib/window.c b/lib/window.c
new file mode 100644 (file)
index 0000000..749279b
--- /dev/null
@@ -0,0 +1,54 @@
+/********************************************************************
+ *                                                                  *
+ * 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: window functions
+ author: Monty <xiphmont@mit.edu>
+ modifications by: Monty
+ last modification date: Jul 27 1999
+
+ ********************************************************************/
+
+#include <stdlib.h>
+#include <math.h>
+
+/* The 'vorbis window' is sin(sin(x)*sin(x)*2pi) */
+
+double *_vorbis_window(int window,int left,int right){
+  double *ret=calloc(window,sizeof(double));
+  int leftbegin=window/4-left/2;
+  int rightbegin=window-window/4-right/2;
+  int i;
+  
+  for(i=0;i<left;i++){
+    double x=(i+.5)/left*M_PI/2.;
+    x=sin(x);
+    x*=x;
+    x*=M_PI/2.;
+    x=sin(x);
+    ret[i+leftbegin]=x;
+  }
+
+  for(i=leftbegin+left;i<rightbegin;i++)
+    ret[i]=1.;
+
+  for(i=0;i<right;i++){
+    double x=(right-i-.5)/right*M_PI/2.;
+    x=sin(x);
+    x*=x;
+    x*=M_PI/2.;
+    x=sin(x);
+    ret[i+rightbegin]=x;
+  }
+
+  return(ret);
+}
diff --git a/lib/window.h b/lib/window.h
new file mode 100644 (file)
index 0000000..6442401
--- /dev/null
@@ -0,0 +1,26 @@
+/********************************************************************
+ *                                                                  *
+ * 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: window functions
+ author: Monty <xiphmont@mit.edu>
+ modifications by: Monty
+ last modification date: Jul 27 1999
+
+ ********************************************************************/
+
+#ifndef _V_WINDOW_
+#define _V_WINDOW_
+
+extern double *_vorbis_window(int window,int left,int right);
+
+#endif