Ultra-wideband VBR seems to work. Also, fixed a bug for wideband VBR.
[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 1000
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}, /* silence */
50    { 3.9,  2.5,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0,  0.0, -1.0}, /*  2 kbps */
51    { 8.0,  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 ((voicing<.3 && non_st < .2 && pow_ener < 1.2*vbr->noise_level)
151        || (voicing<.2 && non_st < .1))
152    {
153       float tmp;
154       va = 0;
155       vbr->consec_noise++;
156       if (pow_ener > 3*vbr->noise_level)
157          tmp = 3*vbr->noise_level;
158       else 
159          tmp = pow_ener;
160       if (vbr->consec_noise>=4)
161       {
162          vbr->noise_accum = .95*vbr->noise_accum + .05*tmp;
163          vbr->noise_accum_count = .95*vbr->noise_accum_count + .05;
164       }
165    } else {
166       va = 1;
167       vbr->consec_noise=0;
168    }
169
170    /* Checking for very low absolute energy */
171    if (ener < 30000)
172    {
173       qual -= .7;
174       if (ener < 10000)
175          qual-=.7;
176       if (ener < 3000)
177          qual-=.7;
178    } else {
179       float short_diff, long_diff;
180       short_diff = log((ener+1)/(1+vbr->last_energy));
181       long_diff = log((ener+1)/(1+vbr->average_energy));
182       /*fprintf (stderr, "%f %f\n", short_diff, long_diff);*/
183
184       if (long_diff<-5)
185          long_diff=-5;
186       if (long_diff>2)
187          long_diff=2;
188
189       if (long_diff>0)
190          qual += .6*long_diff;
191       if (long_diff<0)
192          qual += .5*long_diff;
193       if (short_diff>0)
194       {
195          if (short_diff>5)
196             short_diff=5;
197          qual += .5*short_diff;
198       }
199       /* Checking for energy increases */
200       if (ener2 > 1.6*ener1)
201          qual += .5;
202    }
203    vbr->last_energy = ener;
204    vbr->soft_pitch = .6*vbr->soft_pitch + .4*pitch_coef;
205    qual += 2.2*((pitch_coef-.4) + (vbr->soft_pitch-.4));
206
207    if (qual < vbr->last_quality)
208       qual = .5*qual + .5*vbr->last_quality;
209    if (qual<4)
210       qual=4;
211    if (qual>10)
212       qual=10;
213    
214    if (vbr->consec_noise>=2)
215       qual-=1.3;
216    if (vbr->consec_noise>=5)
217       qual-=1.3;
218    if (vbr->consec_noise>=12)
219       qual-=1.3;
220    
221    vbr->last_pitch_coef = pitch_coef;
222    vbr->last_quality = qual;
223
224    for (i=VBR_MEMORY_SIZE-1;i>0;i--)
225       vbr->last_log_energy[i] = vbr->last_log_energy[i-1];
226    vbr->last_log_energy[0] = log_energy;
227
228    /*printf ("VBR: %f %f %f %d %f\n", (float)(log_energy-log(vbr->average_energy+MIN_ENERGY)), non_st, voicing, va, vbr->noise_level);*/
229
230    return qual;
231 }
232
233 void vbr_destroy(VBRState *vbr)
234 {
235 }