Add RCS ID tags en masse
[platform/upstream/libvorbis.git] / lib / envelope.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5  * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
6  * PLEASE READ THESE TERMS DISTRIBUTING.                            *
7  *                                                                  *
8  * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *
9  * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *
10  * http://www.xiph.org/                                             *
11  *                                                                  *
12  ********************************************************************
13
14  function: PCM data envelope analysis and manipulation
15  author: Monty <xiphmont@mit.edu>
16  modifications by: Monty
17  last modification date: Jun 17 1999
18
19  Vorbis manipulates the dynamic range of the incoming PCM data
20  envelope to minimise time-domain energy leakage from percussive and
21  plosive waveforms being quantized in the MDCT domain.
22
23  ********************************************************************/
24
25 static const char rcsid[] = "$Id";
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <math.h>
30
31 static typedef struct {
32   int divisor;
33   double *window;
34 } envelope_lookup;
35
36 static double oPI  = 3.14159265358979323846;
37
38 envelope_lookup *init_envelope(int length,int divleng){
39   envelope_lookup *ret=malloc(sizeof(envelope_lookup));
40   int i;
41
42   ret->length=divleng;
43   ret->window=malloc(divleng*sizeof(double)*2);
44
45   /* We just use a straight sin^2(x) window for this */
46   for(i=0;i<divleng*2;i++){
47     double temp=sin((i+.5)/divleng*oPI);
48     ret->window[i]=temp*temp;
49   }
50 }
51
52 /* right now, we do things simple and dirty.  Should this prove
53    inadequate, then we'll think of something different.  The details
54    of the encoding format do not depend on the exact behavior, only
55    the format of the bits that come out.
56
57    Using residual from an LPC whitening filter to judge envelope
58    energy would probably yield cleaner results, but that's slow.
59    Let's see if simple delta analysis gives us acceptible results.  */
60
61 int analyze_envelope0(double *vector, envelope_lookup *init, int n,
62                        double *deltas){
63
64   int divisor=init->length;
65   int divs=n/divisor-1;
66   double *win=init->window;
67   int i,j,count=0;
68
69   double max,spanlo,spanhi;
70   
71   /* initial and final blocks are special cases. Eg:
72      ______________                  
73                    \        
74      |_______|______\|_______|_______|
75
76                 ___________             
77                /           \
78      |_______|/______|______\|_______|
79
80                         _____________
81                        /    
82      |_______|_______|/______|_______|
83  
84      as we go block by block, we watch the collective metrics span. If we 
85      span the threshhold (assuming the threshhold is active), we use an 
86      abbreviated vector */
87   
88   /* initial frame */
89   max=0;
90   for(i=1;i<divisor;i++){
91     double temp=abs(vector[i-1]-vector[i]);
92     if(max<temp)max=temp;
93   }
94   for(;i<divisor*2;i++){
95     double temp=abs(win[i-1]*vector[i-1]-win[i]*vector[i]);
96     if(max<temp)max=temp;
97   }
98   spanlo=spanhi=deltas[count++]=max;
99
100   /* mid frames */
101   for(j=divisor;j<n-divisor*2;j+=divisor){
102     max=0;
103     for(i=1;i<divisor*2;i++){
104       double temp=abs(win[i-1]*vector[j+i-1]-win[i]*vector[j+i]);
105       if(max<temp)max=temp;
106     }
107     deltas[count++]=max;
108     if(max<spanlo)spanlo=max;
109     if(max>spanhi)spanhi=max;
110     if(threshhold>1 && spanlo*threshhold<spanhi)
111       abbrevflag=1;
112     if(abbrevflag && j>n0-divisor/2)break;
113   }
114
115   /* last frame */
116   if(!abbrevflag){
117     max=0;
118     for(i=1;i<divisor;i++){
119       double temp=abs(win[i-1]*vector[j+i-1]-win[i]*vector[j+i]);
120       if(max<temp)max=temp;
121     }
122     for(;i<divisor*2;i++){
123       double temp=abs(vector[j+i-1]-vector[j+i]);
124       if(max<temp)max=temp;
125     }
126     deltas[count++]=max;
127     if(max<spanlo)spanlo=max;
128     if(max>spanhi)spanhi=max;
129     if(threshhold>1 && spanlo*threshhold<spanhi)
130       abbrevflag=1;
131   }
132
133   if(abbrevflag)return(n0);
134   return(n);
135 }  
136
137 /* also decide if we're going with a full sized or abbreviated
138    vector. Some encoding tactics might want to use envelope massaging
139    fully and discard abbreviated vectors entriely.  We make that
140    decision here */
141
142 int analyze_envelope1(envelope_lookup *init,int n,
143                       double triggerthresh,double spanthresh,
144                       double *deltas){
145
146   /* Look at the delta values; decide if we need to do any envelope
147      manipulation at all on this vector; if so, choose the
148      multipliers and placeholders.
149
150      '0' is a placeholder.  Other values specify a
151      multiplier/divisor. Multipliers are used by the decoder, divisors
152      in the encoder.  The mapped m/d value for each segment is
153      2^(n-1).  Placeholders (zeros) take on the value of the last
154      non-zero multiplier/divisor.  When the placeholder is not
155      preceeded by a non-placeholder value in the current vector, it
156      assumes the value of the *next* non-zero value.  In this way, the
157      vector manipulation is local to the current vector and does not
158      rely on preceeding vectors.
159
160   */
161   
162   /* scan forward with sliding windows; we start manipulating envelopes
163      when the collective deltas span over a threshhold. If in fact we
164      begin manipulating, we can manage on a finer scale than the
165      original threshhold. first look for the larger threshhold and if
166      we span it, manipulate the vector to hold within the smaller span
167      threshhold. */
168
169   /* scan for the trigger */
170
171   int divisor=init->length;
172   int divs=n/divisor-1;
173   int i,triggerflag=0;
174   double spanlo,spanhi;
175   
176   spanlo=spanhi=deltas[0];
177
178   for(i=1;i<divs;i++){
179     double max=deltas[i];
180     if(max<spanlo)spanlo=max;
181     if(max>spanhi)spanhi=max;
182     if(spanlo*triggerthresh<spanhi){
183       triggerflag=1;
184       break;
185     }
186   }
187
188   if(triggerflag){
189     /* choose divisors/multipliers to fit the vector into the
190        specified span.  In the decoder, these values are *multipliers*, so  */
191
192
193
194
195
196
197
198
199
200
201
202
203
204   }
205   return(triggerflag);
206 }
207