| @@ -1,334 +0,0 @@ |
| 1 | | −/* |
| 2 | | − * Copyright (C) 2004 Alex Beregszaszi & Pierre Lombard |
| 3 | | − * |
| 4 | | − * This file is part of mpv. |
| 5 | | − * |
| 6 | | − * mpv 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 | | − * mpv 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 mpv. If not, see <http://www.gnu.org/licenses/>. |
| 18 | | − */ |
| 19 | | − |
| 20 | | −#include <stdio.h> |
| 21 | | −#include <stdlib.h> |
| 22 | | −#include <string.h> |
| 23 | | − |
| 24 | | −#include <inttypes.h> |
| 25 | | −#include <math.h> |
| 26 | | −#include <limits.h> |
| 27 | | − |
| 28 | | −#include "common/common.h" |
| 29 | | −#include "af.h" |
| 30 | | − |
| 31 | | −// Methods: |
| 32 | | −// 1: uses a 1 value memory and coefficients new=a*old+b*cur (with a+b=1) |
| 33 | | −// 2: uses several samples to smooth the variations (standard weighted mean |
| 34 | | −// on past samples) |
| 35 | | − |
| 36 | | −// Size of the memory array |
| 37 | | −// FIXME: should depend on the frequency of the data (should be a few seconds) |
| 38 | | −#define NSAMPLES 128 |
| 39 | | − |
| 40 | | −// If summing all the mem[].len is lower than MIN_SAMPLE_SIZE bytes, then we |
| 41 | | −// choose to ignore the computed value as it's not significant enough |
| 42 | | −// FIXME: should depend on the frequency of the data (0.5s maybe) |
| 43 | | −#define MIN_SAMPLE_SIZE 32000 |
| 44 | | − |
| 45 | | −// mul is the value by which the samples are scaled |
| 46 | | −// and has to be in [MUL_MIN, MUL_MAX] |
| 47 | | −#define MUL_INIT 1.0 |
| 48 | | −#define MUL_MIN 0.1 |
| 49 | | −#define MUL_MAX 5.0 |
| 50 | | − |
| 51 | | −// Silence level |
| 52 | | −// FIXME: should be relative to the level of the samples |
| 53 | | −#define SIL_S16 (SHRT_MAX * 0.01) |
| 54 | | −#define SIL_FLOAT 0.01 |
| 55 | | − |
| 56 | | −// smooth must be in ]0.0, 1.0[ |
| 57 | | −#define SMOOTH_MUL 0.06 |
| 58 | | −#define SMOOTH_LASTAVG 0.06 |
| 59 | | − |
| 60 | | −#define DEFAULT_TARGET 0.25 |
| 61 | | − |
| 62 | | −// Data for specific instances of this filter |
| 63 | | −typedef struct af_volume_s |
| 64 | | −{ |
| 65 | | − int method; // method used |
| 66 | | − float mul; |
| 67 | | − // method 1 |
| 68 | | − float lastavg; // history value of the filter |
| 69 | | − // method 2 |
| 70 | | − int idx; |
| 71 | | − struct { |
| 72 | | − float avg; // average level of the sample |
| 73 | | − int len; // sample size (weight) |
| 74 | | − } mem[NSAMPLES]; |
| 75 | | − // "Ideal" level |
| 76 | | − float mid_s16; |
| 77 | | − float mid_float; |
| 78 | | −}af_drc_t; |
| 79 | | − |
| 80 | | −// Initialization and runtime control |
| 81 | | −static int control(struct af_instance* af, int cmd, void* arg) |
| 82 | | −{ |
| 83 | | − switch(cmd){ |
| 84 | | − case AF_CONTROL_REINIT: |
| 85 | | − // Sanity check |
| 86 | | − if(!arg) return AF_ERROR; |
| 87 | | − |
| 88 | | − mp_audio_force_interleaved_format((struct mp_audio*)arg); |
| 89 | | − mp_audio_copy_config(af->data, (struct mp_audio*)arg); |
| 90 | | − |
| 91 | | − if(((struct mp_audio*)arg)->format != (AF_FORMAT_S16)){ |
| 92 | | − mp_audio_set_format(af->data, AF_FORMAT_FLOAT); |
| 93 | | − } |
| 94 | | − return af_test_output(af,(struct mp_audio*)arg); |
| 95 | | − } |
| 96 | | − return AF_UNKNOWN; |
| 97 | | −} |
| 98 | | − |
| 99 | | −static void method1_int16(af_drc_t *s, struct mp_audio *c) |
| 100 | | −{ |
| 101 | | − register int i = 0; |
| 102 | | − int16_t *data = (int16_t*)c->planes[0]; // Audio data |
| 103 | | − int len = c->samples*c->nch; // Number of samples |
| 104 | | − float curavg = 0.0, newavg, neededmul; |
| 105 | | − int tmp; |
| 106 | | − |
| 107 | | − for (i = 0; i < len; i++) |
| 108 | | − { |
| 109 | | − tmp = data[i]; |
| 110 | | − curavg += tmp * tmp; |
| 111 | | − } |
| 112 | | − curavg = sqrt(curavg / (float) len); |
| 113 | | − |
| 114 | | − // Evaluate an adequate 'mul' coefficient based on previous state, current |
| 115 | | − // samples level, etc |
| 116 | | − |
| 117 | | − if (curavg > SIL_S16) |
| 118 | | − { |
| 119 | | − neededmul = s->mid_s16 / (curavg * s->mul); |
| 120 | | − s->mul = (1.0 - SMOOTH_MUL) * s->mul + SMOOTH_MUL * neededmul; |
| 121 | | − |
| 122 | | − // clamp the mul coefficient |
| 123 | | − s->mul = MPCLAMP(s->mul, MUL_MIN, MUL_MAX); |
| 124 | | − } |
| 125 | | − |
| 126 | | − // Scale & clamp the samples |
| 127 | | − for (i = 0; i < len; i++) |
| 128 | | − { |
| 129 | | − tmp = s->mul * data[i]; |
| 130 | | − tmp = MPCLAMP(tmp, SHRT_MIN, SHRT_MAX); |
| 131 | | − data[i] = tmp; |
| 132 | | − } |
| 133 | | − |
| 134 | | − // Evaluation of newavg (not 100% accurate because of values clamping) |
| 135 | | − newavg = s->mul * curavg; |
| 136 | | − |
| 137 | | − // Stores computed values for future smoothing |
| 138 | | − s->lastavg = (1.0 - SMOOTH_LASTAVG) * s->lastavg + SMOOTH_LASTAVG * newavg; |
| 139 | | −} |
| 140 | | − |
| 141 | | −static void method1_float(af_drc_t *s, struct mp_audio *c) |
| 142 | | −{ |
| 143 | | − register int i = 0; |
| 144 | | − float *data = (float*)c->planes[0]; // Audio data |
| 145 | | − int len = c->samples*c->nch; // Number of samples |
| 146 | | − float curavg = 0.0, newavg, neededmul, tmp; |
| 147 | | − |
| 148 | | − for (i = 0; i < len; i++) |
| 149 | | − { |
| 150 | | − tmp = data[i]; |
| 151 | | − curavg += tmp * tmp; |
| 152 | | − } |
| 153 | | − curavg = sqrt(curavg / (float) len); |
| 154 | | − |
| 155 | | − // Evaluate an adequate 'mul' coefficient based on previous state, current |
| 156 | | − // samples level, etc |
| 157 | | − |
| 158 | | − if (curavg > SIL_FLOAT) // FIXME |
| 159 | | − { |
| 160 | | − neededmul = s->mid_float / (curavg * s->mul); |
| 161 | | − s->mul = (1.0 - SMOOTH_MUL) * s->mul + SMOOTH_MUL * neededmul; |
| 162 | | − |
| 163 | | − // clamp the mul coefficient |
| 164 | | − s->mul = MPCLAMP(s->mul, MUL_MIN, MUL_MAX); |
| 165 | | − } |
| 166 | | − |
| 167 | | − // Scale & clamp the samples |
| 168 | | − for (i = 0; i < len; i++) |
| 169 | | − data[i] *= s->mul; |
| 170 | | − |
| 171 | | − // Evaluation of newavg (not 100% accurate because of values clamping) |
| 172 | | − newavg = s->mul * curavg; |
| 173 | | − |
| 174 | | − // Stores computed values for future smoothing |
| 175 | | − s->lastavg = (1.0 - SMOOTH_LASTAVG) * s->lastavg + SMOOTH_LASTAVG * newavg; |
| 176 | | −} |
| 177 | | − |
| 178 | | −static void method2_int16(af_drc_t *s, struct mp_audio *c) |
| 179 | | −{ |
| 180 | | − register int i = 0; |
| 181 | | − int16_t *data = (int16_t*)c->planes[0]; // Audio data |
| 182 | | − int len = c->samples*c->nch; // Number of samples |
| 183 | | − float curavg = 0.0, newavg, avg = 0.0; |
| 184 | | − int tmp, totallen = 0; |
| 185 | | − |
| 186 | | − for (i = 0; i < len; i++) |
| 187 | | − { |
| 188 | | − tmp = data[i]; |
| 189 | | − curavg += tmp * tmp; |
| 190 | | − } |
| 191 | | − curavg = sqrt(curavg / (float) len); |
| 192 | | − |
| 193 | | − // Evaluate an adequate 'mul' coefficient based on previous state, current |
| 194 | | − // samples level, etc |
| 195 | | − for (i = 0; i < NSAMPLES; i++) |
| 196 | | − { |
| 197 | | − avg += s->mem[i].avg * (float)s->mem[i].len; |
| 198 | | − totallen += s->mem[i].len; |
| 199 | | − } |
| 200 | | − |
| 201 | | − if (totallen > MIN_SAMPLE_SIZE) |
| 202 | | − { |
| 203 | | − avg /= (float)totallen; |
| 204 | | − if (avg >= SIL_S16) |
| 205 | | − { |
| 206 | | − s->mul = s->mid_s16 / avg; |
| 207 | | − s->mul = MPCLAMP(s->mul, MUL_MIN, MUL_MAX); |
| 208 | | − } |
| 209 | | − } |
| 210 | | − |
| 211 | | − // Scale & clamp the samples |
| 212 | | − for (i = 0; i < len; i++) |
| 213 | | − { |
| 214 | | − tmp = s->mul * data[i]; |
| 215 | | − tmp = MPCLAMP(tmp, SHRT_MIN, SHRT_MAX); |
| 216 | | − data[i] = tmp; |
| 217 | | − } |
| 218 | | − |
| 219 | | − // Evaluation of newavg (not 100% accurate because of values clamping) |
| 220 | | − newavg = s->mul * curavg; |
| 221 | | − |
| 222 | | − // Stores computed values for future smoothing |
| 223 | | − s->mem[s->idx].len = len; |
| 224 | | − s->mem[s->idx].avg = newavg; |
| 225 | | − s->idx = (s->idx + 1) % NSAMPLES; |
| 226 | | −} |
| 227 | | − |
| 228 | | −static void method2_float(af_drc_t *s, struct mp_audio *c) |
| 229 | | −{ |
| 230 | | − register int i = 0; |
| 231 | | − float *data = (float*)c->planes[0]; // Audio data |
| 232 | | − int len = c->samples*c->nch; // Number of samples |
| 233 | | − float curavg = 0.0, newavg, avg = 0.0, tmp; |
| 234 | | − int totallen = 0; |
| 235 | | − |
| 236 | | − for (i = 0; i < len; i++) |
| 237 | | − { |
| 238 | | − tmp = data[i]; |
| 239 | | − curavg += tmp * tmp; |
| 240 | | − } |
| 241 | | − curavg = sqrt(curavg / (float) len); |
| 242 | | − |
| 243 | | − // Evaluate an adequate 'mul' coefficient based on previous state, current |
| 244 | | − // samples level, etc |
| 245 | | − for (i = 0; i < NSAMPLES; i++) |
| 246 | | − { |
| 247 | | − avg += s->mem[i].avg * (float)s->mem[i].len; |
| 248 | | − totallen += s->mem[i].len; |
| 249 | | − } |
| 250 | | − |
| 251 | | − if (totallen > MIN_SAMPLE_SIZE) |
| 252 | | − { |
| 253 | | − avg /= (float)totallen; |
| 254 | | − if (avg >= SIL_FLOAT) |
| 255 | | − { |
| 256 | | − s->mul = s->mid_float / avg; |
| 257 | | − s->mul = MPCLAMP(s->mul, MUL_MIN, MUL_MAX); |
| 258 | | − } |
| 259 | | − } |
| 260 | | − |
| 261 | | − // Scale & clamp the samples |
| 262 | | − for (i = 0; i < len; i++) |
| 263 | | − data[i] *= s->mul; |
| 264 | | − |
| 265 | | − // Evaluation of newavg (not 100% accurate because of values clamping) |
| 266 | | − newavg = s->mul * curavg; |
| 267 | | − |
| 268 | | − // Stores computed values for future smoothing |
| 269 | | − s->mem[s->idx].len = len; |
| 270 | | − s->mem[s->idx].avg = newavg; |
| 271 | | − s->idx = (s->idx + 1) % NSAMPLES; |
| 272 | | −} |
| 273 | | − |
| 274 | | −static int filter(struct af_instance *af, struct mp_audio *data) |
| 275 | | −{ |
| 276 | | − af_drc_t *s = af->priv; |
| 277 | | − |
| 278 | | − if (!data) |
| 279 | | − return 0; |
| 280 | | − |
| 281 | | − if (af_make_writeable(af, data) < 0) { |
| 282 | | − talloc_free(data); |
| 283 | | − return -1; |
| 284 | | − } |
| 285 | | − |
| 286 | | − if(af->data->format == (AF_FORMAT_S16)) |
| 287 | | − { |
| 288 | | − if (s->method == 2) |
| 289 | | − method2_int16(s, data); |
| 290 | | − else |
| 291 | | − method1_int16(s, data); |
| 292 | | − } |
| 293 | | − else if(af->data->format == (AF_FORMAT_FLOAT)) |
| 294 | | − { |
| 295 | | − if (s->method == 2) |
| 296 | | − method2_float(s, data); |
| 297 | | − else |
| 298 | | − method1_float(s, data); |
| 299 | | − } |
| 300 | | − af_add_output_frame(af, data); |
| 301 | | − return 0; |
| 302 | | −} |
| 303 | | − |
| 304 | | −// Allocate memory and set function pointers |
| 305 | | −static int af_open(struct af_instance* af){ |
| 306 | | − int i = 0; |
| 307 | | − af->control=control; |
| 308 | | − af->filter_frame = filter; |
| 309 | | − af_drc_t *priv = af->priv; |
| 310 | | − |
| 311 | | − priv->mul = MUL_INIT; |
| 312 | | − priv->lastavg = ((float)SHRT_MAX) * DEFAULT_TARGET; |
| 313 | | − priv->idx = 0; |
| 314 | | − for (i = 0; i < NSAMPLES; i++) |
| 315 | | − { |
| 316 | | − priv->mem[i].len = 0; |
| 317 | | − priv->mem[i].avg = 0; |
| 318 | | − } |
| 319 | | − priv->mid_s16 = ((float)SHRT_MAX) * priv->mid_float; |
| 320 | | − return AF_OK; |
| 321 | | −} |
| 322 | | − |
| 323 | | −#define OPT_BASE_STRUCT af_drc_t |
| 324 | | −const struct af_info af_info_drc = { |
| 325 | | − .info = "Dynamic range compression filter", |
| 326 | | − .name = "drc", |
| 327 | | − .open = af_open, |
| 328 | | − .priv_size = sizeof(af_drc_t), |
| 329 | | − .options = (const struct m_option[]) { |
| 330 | | − OPT_INTRANGE("method", method, 0, 1, 2, OPTDEF_INT(1)), |
| 331 | | − OPT_FLOAT("target", mid_float, 0, OPTDEF_FLOAT(DEFAULT_TARGET)), |
| 332 | | − {0} |
| 333 | | − }, |
| 334 | | −}; |