Think DTX now works for wideband too
[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 #ifdef DEBUG
39 #include <stdio.h>
40 #endif
41
42 #define sqr(x) ((x)*(x))
43
44 #define MIN_ENERGY 6000
45 #define NOISE_POW .3
46
47
48 float vbr_nb_thresh[8][11]={
49    {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /*   CNG   */
50    {-.01, -0.2, -0.3, -0.4, -0.5, -0.6, -0.7, -0.8, -0.9, -0.9, -1.0}, /*  2 kbps */
51    { 8.5,  5.6,  4.7,  4.2,  3.9,  3.5,  3.0,  2.5,  2.0,  1.0,  0.0}, /*  6 kbps */
52    {11.0,  8.5,  7.5,  6.5,  5.0,  3.9,  3.9,  3.9,  3.5,  3.0,  1.0}, /*  8 kbps */
53    {11.0, 11.0,  9.9,  9.0,  8.0,  7.0,  6.5,  6.0,  5.0,  4.0,  2.0}, /* 11 kbps */
54    {11.0, 11.0, 11.0, 11.0,  9.5,  9.0,  8.0,  7.0,  6.5,  5.0,  3.0}, /* 15 kbps */
55    {11.0, 11.0, 11.0, 11.0, 11.0, 11.0,  9.5,  8.5,  8.0,  6.5,  4.0}, /* 18 kbps */
56    {11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0,  9.8,  7.5,  5.5}  /* 24 kbps */ 
57 };
58
59
60 float vbr_hb_thresh[5][11]={
61    {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /* silence */
62    { 3.9,  2.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -1.0}, /*  2 kbps */
63    {11.0, 11.0,  9.5,  8.5,  7.5,  6.5,  6.0,  5.0,  4.0,  3.0,  1.0}, /*  6 kbps */
64    {11.0, 11.0, 11.0, 11.0, 11.0,  9.5,  8.7,  8.0,  7.0,  6.5,  4.0}, /* 10 kbps */
65    {11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0,  9.8,  7.5,  5.5}  /* 18 kbps */ 
66 };
67
68 float vbr_uhb_thresh[2][11]={
69    {-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0}, /* silence */
70    { 3.9,  2.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -1.0}  /*  2 kbps */
71 };
72
73 void vbr_init(VBRState *vbr)
74 {
75    int i;
76
77    vbr->average_energy=0;
78    vbr->last_energy=1;
79    vbr->accum_sum=0;
80    vbr->energy_alpha=.1;
81    vbr->soft_pitch=0;
82    vbr->last_pitch_coef=0;
83    vbr->last_quality=0;
84
85    vbr->noise_accum = .05*pow(MIN_ENERGY, NOISE_POW);
86    vbr->noise_accum_count=.05;
87    vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count;
88    vbr->consec_noise=0;
89
90
91    for (i=0;i<VBR_MEMORY_SIZE;i++)
92       vbr->last_log_energy[i] = log(MIN_ENERGY);
93 }
94
95
96 /*
97   This function should analyse the signal and decide how critical the
98   coding error will be perceptually. The following factors should be
99   taken into account:
100
101   -Attacks (positive energy derivative) should be coded with more bits
102
103   -Stationary voiced segments should receive more bits
104
105   -Segments with (very) low absolute energy should receive less bits (maybe
106   only shaped noise?)
107
108   -DTX for near-zero energy?
109
110   -Stationary fricative segments should have less bits
111
112   -Temporal masking: when energy slope is decreasing, decrease the bit-rate
113
114   -Decrease bit-rate for males (low pitch)?
115
116   -(wideband only) less bits in the high-band when signal is very 
117   non-stationary (harder to notice high-frequency noise)???
118
119 */
120 #include <stdio.h>
121 float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_coef)
122 {
123    int i;
124    float ener=0, ener1=0, ener2=0;
125    float qual=7;
126    int va;
127    float log_energy;
128    float non_st=0;
129    float voicing;
130    float pow_ener;
131
132    for (i=0;i<len>>1;i++)
133       ener1 += sig[i]*sig[i];
134
135    for (i=len>>1;i<len;i++)
136       ener2 += sig[i]*sig[i];
137    ener=ener1+ener2;
138
139    log_energy = log(ener+MIN_ENERGY);
140    for (i=0;i<VBR_MEMORY_SIZE;i++)
141       non_st += sqr(log_energy-vbr->last_log_energy[i]);
142    non_st =  non_st/(30*VBR_MEMORY_SIZE);
143    if (non_st>1)
144       non_st=1;
145
146    voicing = 3*(pitch_coef-.4)*fabs(pitch_coef-.4);
147    vbr->average_energy = (1-vbr->energy_alpha)*vbr->average_energy + vbr->energy_alpha*ener;
148    vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count;
149    pow_ener = pow(ener,NOISE_POW);
150    if (vbr->noise_accum_count<.06 && ener>MIN_ENERGY)
151       vbr->noise_accum = .05*pow_ener;
152
153    if ((voicing<.3 && non_st < .2 && pow_ener < 1.2*vbr->noise_level)
154        || (voicing<.3 && non_st < .05 && pow_ener < 1.5*vbr->noise_level)
155        || (voicing<.4 && non_st < .05 && pow_ener < 1.2*vbr->noise_level)
156        || (voicing<0 && non_st < .05))
157    {
158       float tmp;
159       va = 0;
160       vbr->consec_noise++;
161       if (pow_ener > 3*vbr->noise_level)
162          tmp = 3*vbr->noise_level;
163       else 
164          tmp = pow_ener;
165       if (vbr->consec_noise>=4)
166       {
167          vbr->noise_accum = .95*vbr->noise_accum + .05*tmp;
168          vbr->noise_accum_count = .95*vbr->noise_accum_count + .05;
169       }
170    } else {
171       va = 1;
172       vbr->consec_noise=0;
173    }
174
175    if (pow_ener < vbr->noise_level && ener>MIN_ENERGY)
176    {
177       vbr->noise_accum = .95*vbr->noise_accum + .05*pow_ener;
178       vbr->noise_accum_count = .95*vbr->noise_accum_count + .05;      
179    }
180
181    /* Checking for very low absolute energy */
182    if (ener < 30000)
183    {
184       qual -= .7;
185       if (ener < 10000)
186          qual-=.7;
187       if (ener < 3000)
188          qual-=.7;
189    } else {
190       float short_diff, long_diff;
191       short_diff = log((ener+1)/(1+vbr->last_energy));
192       long_diff = log((ener+1)/(1+vbr->average_energy));
193       /*fprintf (stderr, "%f %f\n", short_diff, long_diff);*/
194
195       if (long_diff<-5)
196          long_diff=-5;
197       if (long_diff>2)
198          long_diff=2;
199
200       if (long_diff>0)
201          qual += .6*long_diff;
202       if (long_diff<0)
203          qual += .5*long_diff;
204       if (short_diff>0)
205       {
206          if (short_diff>5)
207             short_diff=5;
208          qual += .5*short_diff;
209       }
210       /* Checking for energy increases */
211       if (ener2 > 1.6*ener1)
212          qual += .5;
213    }
214    vbr->last_energy = ener;
215    vbr->soft_pitch = .6*vbr->soft_pitch + .4*pitch_coef;
216    qual += 2.2*((pitch_coef-.4) + (vbr->soft_pitch-.4));
217
218    if (qual < vbr->last_quality)
219       qual = .5*qual + .5*vbr->last_quality;
220    if (qual<4)
221       qual=4;
222    if (qual>10)
223       qual=10;
224    
225    /*
226    if (vbr->consec_noise>=2)
227       qual-=1.3;
228    if (vbr->consec_noise>=5)
229       qual-=1.3;
230    if (vbr->consec_noise>=12)
231       qual-=1.3;
232    */
233    if (vbr->consec_noise>=3)
234       qual=4;
235
236    if (vbr->consec_noise)
237       qual -= 1.0 * (log(3.0 + vbr->consec_noise)-log(3));
238    if (qual<0)
239       qual=0;
240    
241    if (ener<60000)
242    {
243       if (vbr->consec_noise>2)
244          qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3));
245       if (ener<10000&&vbr->consec_noise>2)
246          qual-=0.5*(log(3.0 + vbr->consec_noise)-log(3));
247       if (qual<0)
248          qual=0;
249       qual += .3*log(ener/60000.0);
250    }
251    if (qual<-1)
252       qual=-1;
253
254    /*printf ("%f %f %f %f %d\n", qual, voicing, non_st, pow_ener/(.01+vbr->noise_level), va);*/
255
256    vbr->last_pitch_coef = pitch_coef;
257    vbr->last_quality = qual;
258
259    for (i=VBR_MEMORY_SIZE-1;i>0;i--)
260       vbr->last_log_energy[i] = vbr->last_log_energy[i-1];
261    vbr->last_log_energy[0] = log_energy;
262
263    /*printf ("VBR: %f %f %f %d %f\n", (float)(log_energy-log(vbr->average_energy+MIN_ENERGY)), non_st, voicing, va, vbr->noise_level);*/
264
265    return qual;
266 }
267
268 void vbr_destroy(VBRState *vbr)
269 {
270 }