Improved VBR by adding pitch and some constraints...
[speexdsp.git] / libspeex / vbr.c
1 /* Copyright (C) 2002 Jean-Marc Valin 
2    File: vbr.c
3
4    VBR-related routines
5
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10    
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15    
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 */
21
22 #include "vbr.h"
23
24 void vbr_init(VBRState *vbr)
25 {
26    vbr->average_energy=0;
27    vbr->last_energy=1;
28    vbr->accum_sum=0;
29    vbr->energy_alpha=.1;
30    vbr->soft_pitch=0;
31    vbr->last_pitch_coef=0;
32    vbr->last_quality=0;
33 }
34
35
36 /*
37   This function should analyse the signal and decide how critical the
38   coding error will be perceptually. The following factors should be
39   taken into account:
40
41   -Attacks (positive energy derivative) should be coded with more bits
42
43   -Stationary voiced segments should receive more bits
44
45   -Segments with (very) low absolute energy should receive less bits (maybe
46   only shaped noise?)
47
48   -DTX for near-zero energy?
49
50   -Stationary fricative segments should have less bits
51
52   -Temporal masking: when energy slope is decreasing, decrease the bit-rate
53
54   -Decrease bit-rate for males (low pitch)?
55
56   -(wideband only) less bits in the high-band when signal is very 
57   non-stationary (harder to notice high-frequency noise)???
58
59 */
60 float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_coef)
61 {
62    int i;
63    float ener=0, ener1=0, ener2=0;
64    float qual=0;
65
66    for (i=0;i<len>>1;i++)
67       ener1 += sig[i]*sig[i];
68
69    for (i=len>>1;i<len;i++)
70       ener2 += sig[i]*sig[i];
71    ener=ener1+ener2;
72
73    vbr->average_energy = (1-vbr->energy_alpha)*vbr->average_energy + vbr->energy_alpha*ener;
74    
75    /* Checking for "pseudo temporal masking" */
76    if (ener < .1*vbr->average_energy)
77       qual -= .7;
78    if (ener < .01*vbr->average_energy)
79       qual -= .7;
80    if (ener < .001*vbr->average_energy)
81       qual -= .7;
82    /* Checking for very low absolute energy */
83    if (ener < 30000)
84    {
85       qual -= .7;
86       if (ener < 10000)
87          qual-=.7;
88       if (ener < 3000)
89          qual-=.7;
90    } else {
91       /* Checking for energy increases */
92       if (ener > vbr->last_energy*4.0)
93          qual += 1;
94       if (ener > vbr->last_energy*1.8)
95          qual += 1;
96       if (ener > 3*vbr->average_energy)
97          qual += 1;
98       if (ener2 > 1.6*ener1)
99          qual += .7;
100       if (ener2 < .6*ener1)
101          qual -= .5;
102
103       if (ener < .3*vbr->last_energy)
104          qual -= .6;
105    }
106    vbr->soft_pitch = .6*vbr->soft_pitch + .4*pitch_coef;
107    qual += (pitch_coef-.4) + (vbr->soft_pitch-.4);
108
109    if (qual < vbr->last_quality)
110       qual = .5*qual + .5*vbr->last_quality;
111    if (qual<-3)
112       qual=-3;
113    if (qual>3)
114       qual=3;
115
116    vbr->last_energy = ener;
117    vbr->last_pitch_coef = pitch_coef;
118    vbr->last_quality = qual;
119    return qual;
120 }
121
122 void vbr_destroy(VBRState *vbr)
123 {
124 }