comparison libaf/af_stats.c @ 28661:20787bd5c506

Add statistics audio filter that prints information about the audio stream. patch by Nicolas George, nicolas.george normalesup org
author diego
date Sat, 21 Feb 2009 21:27:27 +0000
parents
children 8e9f6dfd7580
comparison
equal deleted inserted replaced
28660:0812215421d7 28661:20787bd5c506
1 /*
2 * Copyright (C) 2009 Nicolas George <nicolas.george@normalesup.org>
3 *
4 * This file is part of MPlayer.
5 *
6 * MPlayer is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * MPlayer 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <inttypes.h>
24 #include <math.h>
25
26 #include "af.h"
27
28 #define MAX_DB 80
29 #define MIN_VAL 1E-8
30
31 struct af_stats
32 {
33 long long n_samples;
34 double tsquare;
35 int max;
36 long long histogram[65536];
37 };
38
39 static inline int logdb(double v)
40 {
41 return v > 1 ? 0 : v <= MIN_VAL ? MAX_DB - 1 :
42 log(v) / -0.23025850929940456840179914546843642076;
43 }
44
45 static int stats_init(af_instance_t *af, struct af_stats *s, af_data_t *data)
46 {
47 int i;
48
49 if (!data)
50 return AF_ERROR;
51 *(af->data) = *data;
52 af->data->format = AF_FORMAT_S16_NE;
53 af->data->bps = 2;
54 s->n_samples = 0;
55 s->tsquare = 0;
56 s->max = 0;
57 for (i = 0; i < 65536; i++)
58 s->histogram[i] = 0;
59 return af_test_output(af, data);
60 }
61
62 static void stats_print(struct af_stats *s)
63 {
64 int i;
65 long long sum;
66 float v;
67 long long h[MAX_DB];
68
69 s->tsquare /= 32768 * 32768;
70 mp_msg(MSGT_AFILTER, MSGL_INFO, "stats: n_samples: %lld\n", s->n_samples);
71 if (s->n_samples == 0)
72 return;
73 mp_msg(MSGT_AFILTER, MSGL_INFO, "stats: mean_volume: -%d dB\n",
74 logdb(s->tsquare / s->n_samples));
75 mp_msg(MSGT_AFILTER, MSGL_INFO, "stats: max_volume: -%d dB\n",
76 logdb(s->max / 32768.0));
77 for (i = 0; i < MAX_DB; i++)
78 h[i] = 0;
79 for (i = 0; i < 65536; i++) {
80 v = (i - 32768) / 32768.0;
81 h[logdb(v * v)] += s->histogram[i];
82 }
83 for (i = 0; i < MAX_DB; i++)
84 if (h[i] != 0)
85 break;
86 sum = 0;
87 for (; i < MAX_DB; i++) {
88 sum += h[i];
89 mp_msg(MSGT_AFILTER, MSGL_INFO, "stats:histogram_%ddb: %lld\n",
90 i, h[i]);
91 if (sum > s->n_samples / 1000)
92 break;
93 }
94 }
95
96 static int control(struct af_instance_s *af, int cmd, void *arg)
97 {
98 struct af_stats *s = (struct af_stats *)af->setup;
99
100 switch(cmd) {
101 case AF_CONTROL_REINIT:
102 return stats_init(af, s, arg);
103
104 case AF_CONTROL_PRE_DESTROY:
105 stats_print(s);
106 return AF_OK;
107 }
108 return AF_UNKNOWN;
109 }
110
111 static void uninit(struct af_instance_s *af)
112 {
113 if (af->data)
114 free(af->data);
115 if (af->setup)
116 free(af->setup);
117 }
118
119 static af_data_t *play(struct af_instance_s *af, af_data_t *data)
120 {
121 struct af_stats *s = (struct af_stats *)af->setup;
122 int16_t *a, *aend;
123 int v, v2;
124
125 a = data->audio;
126 aend = (int16_t *)((char *)data->audio + data->len);
127 s->n_samples += aend - a;
128 for (; a < aend; a++) {
129 v = *a;
130 v2 = v * v;
131 s->tsquare += v2;
132 s->histogram[v + 32768]++;
133 if (v2 > s->max)
134 s->max = v2;
135 }
136 return data;
137 }
138
139 static int af_open(af_instance_t* af){
140 af->control = control;
141 af->uninit = uninit;
142 af->play = play;
143 af->mul = 1;
144 af->data = malloc(sizeof(af_data_t));
145 af->setup = malloc(sizeof(struct af_stats));
146 if (af->data == NULL || af->setup == NULL)
147 return AF_ERROR;
148 return AF_OK;
149 }
150
151 af_info_t af_info_stats = {
152 "Statistics audio filter",
153 "stats",
154 "Nicolas George",
155 "",
156 0,
157 af_open
158 };