1 /**
2  * @file src/aulevel.c  Audio level
3  *
4  * Copyright (C) 2017 Creytiv.com
5  */
6 
7 #include <math.h>
8 #include <re.h>
9 #include <baresip.h>
10 #include "core.h"
11 
12 
13 /**
14  * Generic routine to calculate RMS (Root-Mean-Square) from
15  * a set of signed 16-bit values
16  *
17  * \verbatim
18 
19 	     .---------------
20 	     |   N-1
21 	     |  ----.
22 	     |  \
23 	     |   \        2
24 	     |    |   s[n]
25 	     |   /
26 	     |  /
27 	 _   |  ----'
28 	  \  |   n=0
29 	   \ |  ------------
30 	    \|       N
31 
32    \endverbatim
33  *
34  * @param data Array of signed 16-bit values
35  * @param len  Number of values
36  *
37  * @return RMS value from 0 to 32768
38  */
calc_rms(const int16_t * data,size_t len)39 static double calc_rms(const int16_t *data, size_t len)
40 {
41 	double sum = 0;
42 	size_t i;
43 
44 	if (!data || !len)
45 		return .0;
46 
47 	for (i = 0; i < len; i++) {
48 		const double sample = data[i];
49 
50 		sum += sample * sample;
51 	}
52 
53 	return sqrt(sum / (double)len);
54 }
55 
56 
57 /**
58  * Calculate the audio level in dBov from a set of audio samples.
59  * dBov is the level, in decibels, relative to the overload point
60  * of the system
61  *
62  * @param sampv Audio samples
63  * @param sampc Number of audio samples
64  *
65  * @return Audio level expressed in dBov
66  */
aulevel_calc_dbov(const int16_t * sampv,size_t sampc)67 double aulevel_calc_dbov(const int16_t *sampv, size_t sampc)
68 {
69 	static const double peak = 32767.0;
70 	double rms, dbov;
71 
72 	if (!sampv || !sampc)
73 		return AULEVEL_MIN;
74 
75 	rms = calc_rms(sampv, sampc) / peak;
76 
77 	dbov = 20 * log10(rms);
78 
79 	if (dbov < AULEVEL_MIN)
80 		dbov = AULEVEL_MIN;
81 	else if (dbov > AULEVEL_MAX)
82 		dbov = AULEVEL_MAX;
83 
84 	return dbov;
85 }
86