Trying a new VBR implementation... still experimental
[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    { 4.5,  3.5,  2.5,  1.5,  0.5,  0.0,  0.0,  0.0,  0.0,  0.0, -1.0}, /*  2 kbps */
51    { 9.5,  7.5,  6.5,  5.5,  5.0,  4.0,  4.5,  3.0,  2.0,  1.0,  0.0}, /*  6 kbps */
52    {11.0,  9.5,  8.5,  7.5,  7.0,  6.5,  6.0,  5.0,  4.0,  3.0,  1.0}, /*  8 kbps */
53    {11.0, 11.0, 11.0,  9.5,  8.5,  7.5,  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.5,  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.5,  7.5,  5.5}  /* 24 kbps */ 
57 };
58
59
60 void vbr_init(VBRState *vbr)
61 {
62    int i;
63
64    vbr->average_energy=0;
65    vbr->last_energy=1;
66    vbr->accum_sum=0;
67    vbr->energy_alpha=.1;
68    vbr->soft_pitch=0;
69    vbr->last_pitch_coef=0;
70    vbr->last_quality=0;
71
72    vbr->noise_accum = .05*pow(MIN_ENERGY, NOISE_POW);
73    vbr->noise_accum_count=.05;
74    vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count;
75    vbr->consec_noise=0;
76
77
78    for (i=0;i<VBR_MEMORY_SIZE;i++)
79       vbr->last_log_energy[i] = log(MIN_ENERGY);
80 }
81
82
83 /*
84   This function should analyse the signal and decide how critical the
85   coding error will be perceptually. The following factors should be
86   taken into account:
87
88   -Attacks (positive energy derivative) should be coded with more bits
89
90   -Stationary voiced segments should receive more bits
91
92   -Segments with (very) low absolute energy should receive less bits (maybe
93   only shaped noise?)
94
95   -DTX for near-zero energy?
96
97   -Stationary fricative segments should have less bits
98
99   -Temporal masking: when energy slope is decreasing, decrease the bit-rate
100
101   -Decrease bit-rate for males (low pitch)?
102
103   -(wideband only) less bits in the high-band when signal is very 
104   non-stationary (harder to notice high-frequency noise)???
105
106 */
107 float vbr_analysis(VBRState *vbr, float *sig, int len, int pitch, float pitch_coef)
108 {
109    int i;
110    float ener=0, ener1=0, ener2=0;
111    float qual=0;
112    int va;
113    float log_energy;
114    float non_st=0;
115    float voicing;
116    float pow_ener;
117
118    for (i=0;i<len>>1;i++)
119       ener1 += sig[i]*sig[i];
120
121    for (i=len>>1;i<len;i++)
122       ener2 += sig[i]*sig[i];
123    ener=ener1+ener2;
124
125    log_energy = log(ener+MIN_ENERGY);
126    for (i=0;i<VBR_MEMORY_SIZE;i++)
127       non_st += sqr(log_energy-vbr->last_log_energy[i]);
128    non_st =  non_st/(30*VBR_MEMORY_SIZE);
129    if (non_st>1)
130       non_st=1;
131
132    voicing = 3*(pitch_coef-.4)*fabs(pitch_coef-.4);
133    vbr->average_energy = (1-vbr->energy_alpha)*vbr->average_energy + vbr->energy_alpha*ener;
134    vbr->noise_level=vbr->noise_accum/vbr->noise_accum_count;
135    pow_ener = pow(ener,NOISE_POW);
136    if ((voicing<.3 && non_st < .2 && pow_ener < 1.2*vbr->noise_level)
137        || (voicing<.2 && non_st < .1))
138    {
139       float tmp;
140       va = 0;
141       vbr->consec_noise++;
142       if (pow_ener > 3*vbr->noise_level)
143          tmp = 3*vbr->noise_level;
144       else 
145          tmp = pow_ener;
146       if (vbr->consec_noise>=4)
147       {
148          vbr->noise_accum = .95*vbr->noise_accum + .05*tmp;
149          vbr->noise_accum_count = .95*vbr->noise_accum_count + .05;
150       }
151    } else {
152       va = 1;
153       vbr->consec_noise=0;
154    }
155
156    /* Checking for "pseudo temporal masking" */
157    if (ener < .1*vbr->average_energy)
158       qual -= .7;
159    if (ener < .01*vbr->average_energy)
160       qual -= .7;
161    if (ener < .001*vbr->average_energy)
162       qual -= .7;
163    /* Checking for very low absolute energy */
164    if (ener < 30000)
165    {
166       qual -= .7;
167       if (ener < 10000)
168          qual-=.7;
169       if (ener < 3000)
170          qual-=.7;
171    } else {
172       /* Checking for energy increases */
173       if (ener > vbr->last_energy*4.0)
174          qual += .7;
175       if (ener > vbr->last_energy*1.8)
176          qual += .7;
177       if (ener > 3*vbr->average_energy)
178          qual += .7;
179       if (ener2 > 1.6*ener1)
180          qual += .7;
181       if (ener2 < .6*ener1)
182          qual -= .5;
183
184       if (ener < .3*vbr->last_energy)
185          qual -= .6;
186    }
187    vbr->soft_pitch = .6*vbr->soft_pitch + .4*pitch_coef;
188    qual += 1.0*((pitch_coef-.4) + (vbr->soft_pitch-.4));
189
190    if (qual < vbr->last_quality)
191       qual = .5*qual + .5*vbr->last_quality;
192    if (qual<-3)
193       qual=-3;
194    if (qual>3)
195       qual=3;
196
197    if (vbr->consec_noise>=1)
198       qual-=1.2;
199    if (vbr->consec_noise>=4)
200       qual-=1.2;
201    if (vbr->consec_noise>=8)
202       qual-=1.2;
203
204    vbr->last_pitch_coef = pitch_coef;
205    vbr->last_quality = qual;
206
207    for (i=VBR_MEMORY_SIZE-1;i>0;i--)
208       vbr->last_log_energy[i] = vbr->last_log_energy[i-1];
209    vbr->last_log_energy[0] = log_energy;
210
211    /*printf ("VBR: %f %f %f %d %f\n", (float)(log_energy-log(vbr->average_energy+MIN_ENERGY)), non_st, voicing, va, vbr->noise_level);*/
212
213    return qual;
214 }
215
216 void vbr_destroy(VBRState *vbr)
217 {
218 }