added const in front of vbr_*_thresh tables
[speexdsp.git] / libspeex / vbr.c
1 /* Copyright (C) 2002 Jean-Marc Valin 
2    File: vbr.c
3
4    VBR-related routines
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9    
10    - Redistributions of source code must retain the above copyright
11    notice, this list of conditions and the following disclaimer.
12    
13    - Redistributions in binary form must reproduce the above copyright
14    notice, this list of conditions and the following disclaimer in the
15    documentation and/or other materials provided with the distribution.
16    
17    - Neither the name of the Xiph.org Foundation nor the names of its
18    contributors may be used to endorse or promote products derived from
19    this software without specific prior written permission.
20    
21    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
25    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 */
34
35 #include "vbr.h"
36 #include <math.h>
37
38
39 #define sqr(x) ((x)*(x))
40
41 #define MIN_ENERGY 6000
42 #define NOISE_POW .3
43
44
45 const float vbr_nb_thresh[9][11]={
46    {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /*   CNG   */
47    { 3.5,  2.5,  2.0,  1.2,  0.5,  0.0, -0.5, -0.7, -0.8, -0.9, -1.0}, /*  2 kbps */
48    {10.0,  6.5,  5.2,  4.5,  3.9,  3.5,  3.0,  2.5,  2.3,  1.8,  1.0}, /*  6 kbps */
49    {11.0,  8.8,  7.5,  6.5,  5.0,  3.9,  3.9,  3.9,  3.5,  3.0,  1.0}, /*  8 kbps */
50    {11.0, 11.0,  9.9,  9.0,  8.0,  7.0,  6.5,  6.0,  5.0,  4.0,  2.0}, /* 11 kbps */
51    {11.0, 11.0, 11.0, 11.0,  9.5,  9.0,  8.0,  7.0,  6.5,  5.0,  3.0}, /* 15 kbps */
52    {11.0, 11.0, 11.0, 11.0, 11.0, 11.0,  9.5,  8.5,  8.0,  6.5,  4.0}, /* 18 kbps */
53    {11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0,  9.8,  7.5,  5.5}, /* 24 kbps */ 
54    { 8.0,  5.0,  3.7,  3.0,  2.5,  2.0,  1.8,  1.5,  1.0,  0.0,  0.0}  /*  4 kbps */
55 };
56
57
58 const float vbr_hb_thresh[5][11]={
59    {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /* silence */
60    {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /*  2 kbps */
61    {11.0, 11.0,  9.5,  8.5,  7.5,  6.0,  5.0,  3.9,  3.0,  2.0,  1.0}, /*  6 kbps */
62    {11.0, 11.0, 11.0, 11.0, 11.0,  9.5,  8.7,  7.8,  7.0,  6.5,  4.0}, /* 10 kbps */
63    {11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0,  9.8,  7.5,  5.5}  /* 18 kbps */ 
64 };
65
66 const float vbr_uhb_thresh[2][11]={
67    {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /* silence */
68    { 3.9,  2.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -1.0}  /*  2 kbps */
69 };
70
71 void vbr_init(VBRState *vbr)
72 {
73    int i;
74
75    vbr->average_energy=0;
76    vbr->last_energy=1;
77    vbr->accum_sum=0;
78    vbr->energy_alpha=.1;
79    vbr->soft_pitch=0;
80    vbr->last_pitch_coef=0;
81    vbr->last_quality=0;
82
83    vbr->noise_accum = .05*pow(MIN_ENERGY, NOISE_POW);
84    vbr->noise_accum_count=.05;
85    vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count;
86    vbr->consec_noise=0;
87
88
89    for (i=0;i<VBR_MEMORY_SIZE;i++)
90       vbr->last_log_energy[i] = log(MIN_ENERGY);
91 }
92
93
94 /*
95   This function should analyse the signal and decide how critical the
96   coding error will be perceptually. The following factors should be
97   taken into account:
98
99   -Attacks (positive energy derivative) should be coded with more bits
100
101   -Stationary voiced segments should receive more bits
102
103   -Segments with (very) low absolute energy should receive less bits (maybe
104   only shaped noise?)
105
106   -DTX for near-zero energy?
107
108   -Stationary fricative segments should have less bits
109
110   -Temporal masking: when energy slope is decreasing, decrease the bit-rate
111
112   -Decrease bit-rate for males (low pitch)?
113
114   -(wideband only) less bits in the high-band when signal is very 
115   non-stationary (harder to notice high-frequency noise)???
116
117 */
118
119 float vbr_analysis(VBRState *vbr, spx_word16_t *sig, int len, int pitch, float pitch_coef)
120 {
121    int i;
122    float ener=0, ener1=0, ener2=0;
123    float qual=7;
124    int va;
125    float log_energy;
126    float non_st=0;
127    float voicing;
128    float pow_ener;
129
130    for (i=0;i<len>>1;i++)
131       ener1 += ((float)sig[i])*sig[i];
132
133    for (i=len>>1;i<len;i++)
134       ener2 += ((float)sig[i])*sig[i];
135    ener=ener1+ener2;
136
137    log_energy = log(ener+MIN_ENERGY);
138    for (i=0;i<VBR_MEMORY_SIZE;i++)
139       non_st += sqr(log_energy-vbr->last_log_energy[i]);
140    non_st =  non_st/(30*VBR_MEMORY_SIZE);
141    if (non_st>1)
142       non_st=1;
143
144    voicing = 3*(pitch_coef-.4)*fabs(pitch_coef-.4);
145    vbr->average_energy = (1-vbr->energy_alpha)*vbr->average_energy + vbr->energy_alpha*ener;
146    vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count;
147    pow_ener = pow(ener,NOISE_POW);
148    if (vbr->noise_accum_count<.06 && ener>MIN_ENERGY)
149       vbr->noise_accum = .05*pow_ener;
150
151    if ((voicing<.3 && non_st < .2 && pow_ener < 1.2*vbr->noise_level)
152        || (voicing<.3 && non_st < .05 && pow_ener < 1.5*vbr->noise_level)
153        || (voicing<.4 && non_st < .05 && pow_ener < 1.2*vbr->noise_level)
154        || (voicing<0 && non_st < .05))
155    {
156       float tmp;
157       va = 0;
158       vbr->consec_noise++;
159       if (pow_ener > 3*vbr->noise_level)
160          tmp = 3*vbr->noise_level;
161       else 
162          tmp = pow_ener;
163       if (vbr->consec_noise>=4)
164       {
165          vbr->noise_accum = .95*vbr->noise_accum + .05*tmp;
166          vbr->noise_accum_count = .95*vbr->noise_accum_count + .05;
167       }
168    } else {
169       va = 1;
170       vbr->consec_noise=0;
171    }
172
173    if (pow_ener < vbr->noise_level && ener>MIN_ENERGY)
174    {
175       vbr->noise_accum = .95*vbr->noise_accum + .05*pow_ener;
176       vbr->noise_accum_count = .95*vbr->noise_accum_count + .05;      
177    }
178
179    /* Checking for very low absolute energy */
180    if (ener < 30000)
181    {
182       qual -= .7;
183       if (ener < 10000)
184          qual-=.7;
185       if (ener < 3000)
186          qual-=.7;
187    } else {
188       float short_diff, long_diff;
189       short_diff = log((ener+1)/(1+vbr->last_energy));
190       long_diff = log((ener+1)/(1+vbr->average_energy));
191       /*fprintf (stderr, "%f %f\n", short_diff, long_diff);*/
192
193       if (long_diff<-5)
194          long_diff=-5;
195       if (long_diff>2)
196          long_diff=2;
197
198       if (long_diff>0)
199          qual += .6*long_diff;
200       if (long_diff<0)
201          qual += .5*long_diff;
202       if (short_diff>0)
203       {
204          if (short_diff>5)
205             short_diff=5;
206          qual += .5*short_diff;
207       }
208       /* Checking for energy increases */
209       if (ener2 > 1.6*ener1)
210          qual += .5;
211    }
212    vbr->last_energy = ener;
213    vbr->soft_pitch = .6*vbr->soft_pitch + .4*pitch_coef;
214    qual += 2.2*((pitch_coef-.4) + (vbr->soft_pitch-.4));
215
216    if (qual < vbr->last_quality)
217       qual = .5*qual + .5*vbr->last_quality;
218    if (qual<4)
219       qual=4;
220    if (qual>10)
221       qual=10;
222    
223    /*
224    if (vbr->consec_noise>=2)
225       qual-=1.3;
226    if (vbr->consec_noise>=5)
227       qual-=1.3;
228    if (vbr->consec_noise>=12)
229       qual-=1.3;
230    */
231    if (vbr->consec_noise>=3)
232       qual=4;
233
234    if (vbr->consec_noise)
235       qual -= 1.0 * (log(3.0 + vbr->consec_noise)-log(3));
236    if (qual<0)
237       qual=0;
238    
239    if (ener<60000)
240    {
241       if (vbr->consec_noise>2)
242          qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3));
243       if (ener<10000&&vbr->consec_noise>2)
244          qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3));
245       if (qual<0)
246          qual=0;
247       qual += .3*log(ener/60000.0);
248    }
249    if (qual<-1)
250       qual=-1;
251
252    /*printf ("%f %f %f %f %d\n", qual, voicing, non_st, pow_ener/(.01+vbr->noise_level), va);*/
253
254    vbr->last_pitch_coef = pitch_coef;
255    vbr->last_quality = qual;
256
257    for (i=VBR_MEMORY_SIZE-1;i>0;i--)
258       vbr->last_log_energy[i] = vbr->last_log_energy[i-1];
259    vbr->last_log_energy[0] = log_energy;
260
261    /*printf ("VBR: %f %f %f %d %f\n", (float)(log_energy-log(vbr->average_energy+MIN_ENERGY)), non_st, voicing, va, vbr->noise_level);*/
262
263    return qual;
264 }
265
266 void vbr_destroy(VBRState *vbr)
267 {
268 }