1 /********************************************************************
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. *
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/ *
12 ********************************************************************
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
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.
23 ********************************************************************/
25 static const char rcsid[] = "$Id";
31 static typedef struct {
36 static double oPI = 3.14159265358979323846;
38 envelope_lookup *init_envelope(int length,int divleng){
39 envelope_lookup *ret=malloc(sizeof(envelope_lookup));
43 ret->window=malloc(divleng*sizeof(double)*2);
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;
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.
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. */
61 int analyze_envelope0(double *vector, envelope_lookup *init, int n,
64 int divisor=init->length;
66 double *win=init->window;
69 double max,spanlo,spanhi;
71 /* initial and final blocks are special cases. Eg:
74 |_______|______\|_______|_______|
78 |_______|/______|______\|_______|
82 |_______|_______|/______|_______|
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
90 for(i=1;i<divisor;i++){
91 double temp=abs(vector[i-1]-vector[i]);
94 for(;i<divisor*2;i++){
95 double temp=abs(win[i-1]*vector[i-1]-win[i]*vector[i]);
98 spanlo=spanhi=deltas[count++]=max;
101 for(j=divisor;j<n-divisor*2;j+=divisor){
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;
108 if(max<spanlo)spanlo=max;
109 if(max>spanhi)spanhi=max;
110 if(threshhold>1 && spanlo*threshhold<spanhi)
112 if(abbrevflag && j>n0-divisor/2)break;
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;
122 for(;i<divisor*2;i++){
123 double temp=abs(vector[j+i-1]-vector[j+i]);
124 if(max<temp)max=temp;
127 if(max<spanlo)spanlo=max;
128 if(max>spanhi)spanhi=max;
129 if(threshhold>1 && spanlo*threshhold<spanhi)
133 if(abbrevflag)return(n0);
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
142 int analyze_envelope1(envelope_lookup *init,int n,
143 double triggerthresh,double spanthresh,
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.
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.
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
169 /* scan for the trigger */
171 int divisor=init->length;
172 int divs=n/divisor-1;
174 double spanlo,spanhi;
176 spanlo=spanhi=deltas[0];
179 double max=deltas[i];
180 if(max<spanlo)spanlo=max;
181 if(max>spanhi)spanhi=max;
182 if(spanlo*triggerthresh<spanhi){
189 /* choose divisors/multipliers to fit the vector into the
190 specified span. In the decoder, these values are *multipliers*, so */