Initial revision
[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 #include <stdlib.h>
26 #include <stdio.h>
27 #include <math.h>
28
29 static typedef struct {
30   int divisor;
31   double *window;
32 } envelope_lookup;
33
34 static double oPI  = 3.14159265358979323846;
35
36 envelope_lookup *init_envelope(int length,int divleng){
37   envelope_lookup *ret=malloc(sizeof(envelope_lookup));
38   int i;
39
40   ret->length=divleng;
41   ret->window=malloc(divleng*sizeof(double)*2);
42
43   /* We just use a straight sin^2(x) window for this */
44   for(i=0;i<divleng*2;i++){
45     double temp=sin((i+.5)/divleng*oPI);
46     ret->window[i]=temp*temp;
47   }
48 }
49
50 /* right now, we do things simple and dirty.  Should this prove
51    inadequate, then we'll think of something different.  The details
52    of the encoding format do not depend on the exact behavior, only
53    the format of the bits that come out.
54
55    Using residual from an LPC whitening filter to judge envelope
56    energy would probably yield cleaner results, but that's slow.
57    Let's see if simple delta analysis gives us acceptible results.  */
58
59 int analyze_envelope0(double *vector, envelope_lookup *init, int n,
60                        double *deltas){
61
62   int divisor=init->length;
63   int divs=n/divisor-1;
64   double *win=init->window;
65   int i,j,count=0;
66
67   double max,spanlo,spanhi;
68   
69   /* initial and final blocks are special cases. Eg:
70      ______________                  
71                    \        
72      |_______|______\|_______|_______|
73
74                 ___________             
75                /           \
76      |_______|/______|______\|_______|
77
78                         _____________
79                        /    
80      |_______|_______|/______|_______|
81  
82      as we go block by block, we watch the collective metrics span. If we 
83      span the threshhold (assuming the threshhold is active), we use an 
84      abbreviated vector */
85   
86   /* initial frame */
87   max=0;
88   for(i=1;i<divisor;i++){
89     double temp=abs(vector[i-1]-vector[i]);
90     if(max<temp)max=temp;
91   }
92   for(;i<divisor*2;i++){
93     double temp=abs(win[i-1]*vector[i-1]-win[i]*vector[i]);
94     if(max<temp)max=temp;
95   }
96   spanlo=spanhi=deltas[count++]=max;
97
98   /* mid frames */
99   for(j=divisor;j<n-divisor*2;j+=divisor){
100     max=0;
101     for(i=1;i<divisor*2;i++){
102       double temp=abs(win[i-1]*vector[j+i-1]-win[i]*vector[j+i]);
103       if(max<temp)max=temp;
104     }
105     deltas[count++]=max;
106     if(max<spanlo)spanlo=max;
107     if(max>spanhi)spanhi=max;
108     if(threshhold>1 && spanlo*threshhold<spanhi)
109       abbrevflag=1;
110     if(abbrevflag && j>n0-divisor/2)break;
111   }
112
113   /* last frame */
114   if(!abbrevflag){
115     max=0;
116     for(i=1;i<divisor;i++){
117       double temp=abs(win[i-1]*vector[j+i-1]-win[i]*vector[j+i]);
118       if(max<temp)max=temp;
119     }
120     for(;i<divisor*2;i++){
121       double temp=abs(vector[j+i-1]-vector[j+i]);
122       if(max<temp)max=temp;
123     }
124     deltas[count++]=max;
125     if(max<spanlo)spanlo=max;
126     if(max>spanhi)spanhi=max;
127     if(threshhold>1 && spanlo*threshhold<spanhi)
128       abbrevflag=1;
129   }
130
131   if(abbrevflag)return(n0);
132   return(n);
133 }  
134
135 /* also decide if we're going with a full sized or abbreviated
136    vector. Some encoding tactics might want to use envelope massaging
137    fully and discard abbreviated vectors entriely.  We make that
138    decision here */
139
140 int analyze_envelope1(envelope_lookup *init,int n,
141                       double triggerthresh,double spanthresh,
142                       double *deltas){
143
144   /* Look at the delta values; decide if we need to do any envelope
145      manipulation at all on this vector; if so, choose the
146      multipliers and placeholders.
147
148      '0' is a placeholder.  Other values specify a
149      multiplier/divisor. Multipliers are used by the decoder, divisors
150      in the encoder.  The mapped m/d value for each segment is
151      2^(n-1).  Placeholders (zeros) take on the value of the last
152      non-zero multiplier/divisor.  When the placeholder is not
153      preceeded by a non-placeholder value in the current vector, it
154      assumes the value of the *next* non-zero value.  In this way, the
155      vector manipulation is local to the current vector and does not
156      rely on preceeding vectors.
157
158   */
159   
160   /* scan forward with sliding windows; we start manipulating envelopes
161      when the collective deltas span over a threshhold. If in fact we
162      begin manipulating, we can manage on a finer scale than the
163      original threshhold. first look for the larger threshhold and if
164      we span it, manipulate the vector to hold within the smaller span
165      threshhold. */
166
167   /* scan for the trigger */
168
169   int divisor=init->length;
170   int divs=n/divisor-1;
171   int i,triggerflag=0;
172   double spanlo,spanhi;
173   
174   spanlo=spanhi=deltas[0];
175
176   for(i=1;i<divs;i++){
177     double max=deltas[i];
178     if(max<spanlo)spanlo=max;
179     if(max>spanhi)spanhi=max;
180     if(spanlo*triggerthresh<spanhi){
181       triggerflag=1;
182       break;
183     }
184   }
185
186   if(triggerflag){
187     /* choose divisors/multipliers to fit the vector into the
188        specified span.  In the decoder, these values are *multipliers*, so  */
189
190
191
192
193
194
195
196
197
198
199
200
201
202   }
203   return(triggerflag);
204 }
205