From patchwork Mon Jun 17 11:18:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yigithan Yigit X-Patchwork-Id: 49970 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a59:9196:0:b0:460:55fa:d5ed with SMTP id s22csp1862358vqg; Mon, 17 Jun 2024 04:18:47 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUhpejCuMrINQ+H7IY2eb9KAjJAIQ5/RxnsQ0dtziXqJJupIFld3lovL41DjCsrG/rF+tnJTEmuHHw9GsHGMh2Nl5NHXQn2jG6h3Q== X-Google-Smtp-Source: AGHT+IEmCQIjkFigq2iWAGgvpaBbjSJsz3fVTCfiustXzYSc/4/g9Agy9kRthLKTIFpetyk8RcI9 X-Received: by 2002:ac2:51b9:0:b0:52c:5925:fc9e with SMTP id 2adb3069b0e04-52ca6e653abmr5603961e87.25.1718623126847; Mon, 17 Jun 2024 04:18:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1718623126; cv=none; d=google.com; s=arc-20160816; b=WvOVvUTCpuRBZ4gGHD2nrQRF3kOBn2SpDMGGXKEvbGLHtwjtbAEYhOyEEtTCeK41OY SxZT9H6R/uqXwacZtTdw+Xvr45wooJUf3Hmi5OJErdwOJY/RtkwkKXvbSStpULlBkGq7 Sl/vvcgMhqU0I/xZeW5kQrM3KkVmXPWjtlCGmuj235TKJrhFtwy1RpfU6eIzKyOQIXIZ Etc/Os9TqSUvi0Z5iT4+/xxjm0fEXDmsKU1Kv8L11iLaQlZ6axjF2yYCgNoxLVmyNe+g venAT/Ai2A2MxVR3IJix3F+yGrxCIxcfK709avM6l4l6kHBMYCcPUc2LI0w8NIgkIc8k 8BEg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=1312aOE6n9l91LYzCrP4C7b3bDgnyvjAg3KzRf38lA8=; fh=oYrUj4vT4ivb560z23e71q/pal11/Mm+yKMO8RKszaM=; b=odRRHUtpxxyUBYpDmrA1XQxlhqrGwY4XR1X2u1x5JiKMecN7Ve+68GvsrOmN31+pI3 bC96a0A3nAgueSjvdTE9GDsHnbTRMtNbC8P3ixfJPuVWFfo67oMvqrlaLcI5a/ul7XLl iK/mBJL12wNoNQ3U8te2wZi1Sf3j7WaBaAM3OzTZ55KFyMNuzxqmie3hQOZDLwoLNZ6d mGpV/Py6jl9oIkyU2J8VmsSpIMZoiT4vt2CA0gWmHLj5s5RwLh/bv9s5+TkH+lt6OSw0 3pB+ERoH8JFt/Bn0rbJvxcBr3uUeyTG3vn5R/knC+oalNl9ZKhQSVq13amUCartQO82P tnWg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b=DyB6MhxH; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id 2adb3069b0e04-52ca28725bcsi2674795e87.317.2024.06.17.04.18.46; Mon, 17 Jun 2024 04:18:46 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b=DyB6MhxH; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DB7AD68D768; Mon, 17 Jun 2024 14:18:31 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lj1-f176.google.com (mail-lj1-f176.google.com [209.85.208.176]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4783468D770 for ; Mon, 17 Jun 2024 14:18:22 +0300 (EEST) Received: by mail-lj1-f176.google.com with SMTP id 38308e7fff4ca-2ebe40673d8so44817201fa.3 for ; Mon, 17 Jun 2024 04:18:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1718623101; x=1719227901; darn=ffmpeg.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=rC+G1COcA2uRwnPHyU33C91MeQaOHt8+sD4bmcdl3Hs=; b=DyB6MhxHCY8nmI3tXcLxJesSau3z7eyROLMajYdyCAsKeKuj6xq9zPbKOUUd/gbiC4 AdUdeO4/efXnncuYPQLj6Kj+M+R9Dal/bUVSjJ0/i1n634nK8MfJSaPMq/+wJ4hkw598 u/MilHmJ1xZVCnS3KWewVVJ57dpR4VzAbt4rHnjnYNtcNA8PVMLx3tnJ39UlwUvUlVXU wAtMzRK9p2R7bpmZWYXP2Kr4xOyr/x1ZCU2QhrVIGup0DuEK0FPNxK0x9Kzj89bD3kAG kxzmc89Ihk2DJ31pqS7GHVILpg7mUPfV/aoEZAfO8M8B3X730ygyhZ2kwFLGPo+xBVst CehA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718623101; x=1719227901; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=rC+G1COcA2uRwnPHyU33C91MeQaOHt8+sD4bmcdl3Hs=; b=RpAyU+vFALxO3+60S4jb4hMWxZTFymnx6AWe+iNGiVoeNZ0qIl9EdaYk+WbQ0MkAXX +1hnVDGJ/bzcWk5ggSSGX6Vyldi6R2L6bXInzNBuUmmsyhs/kBnsMTpArTl8dAgyjVZz lT6+L6elc9o1mdH1Dpmiqf5x10KO8AqNI7x0qX6qOerRHU3oCnDo+G7wGk4QCFaOzuKh //QbzsibgRx+SSrLw5qed2+Sq7CrB/Qb+WQuqjvG2jeGV8hYyDgq+P1oX/hKeMwoexIu IFZgQ0S8lTEHOT6PtxhJnBV4YUTtOO1iJiWYXLyjL/6dPW1/Z8ghPrBy9I0n4ogECNWW GxuQ== X-Gm-Message-State: AOJu0YydA/xf1FlXExtB4i6Cnk5fI0oLXd+ksE7yDyNqI3EqRskUsCzB SgSvVtUGfKrCcGrw5fpuwUxRWCK/zsuktkZXl6Owqr94FP5w4IeYixkI+Q== X-Received: by 2002:a2e:9888:0:b0:2eb:da6b:683b with SMTP id 38308e7fff4ca-2ec0e5c6487mr55082211fa.15.1718623100663; Mon, 17 Jun 2024 04:18:20 -0700 (PDT) Received: from localhost.localdomain ([88.239.140.156]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-422f5f33c38sm157888015e9.9.2024.06.17.04.18.19 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Mon, 17 Jun 2024 04:18:20 -0700 (PDT) From: Yigithan Yigit To: ffmpeg-devel@ffmpeg.org Date: Mon, 17 Jun 2024 14:18:11 +0300 Message-ID: <20240617111812.84575-3-yigithanyigitdevel@gmail.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240617111812.84575-1-yigithanyigitdevel@gmail.com> References: <20240617111812.84575-1-yigithanyigitdevel@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/3] avfilter/af_volumedetect.c: Add 32bit float audio support X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: thilo.borgmann@mail.de, yigithanyigitdevel@gmail.com Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: EiU//dhSjnTa --- libavfilter/af_volumedetect.c | 159 ++++++++++++++++++++++++++++------ 1 file changed, 133 insertions(+), 26 deletions(-) diff --git a/libavfilter/af_volumedetect.c b/libavfilter/af_volumedetect.c index 327801a7f9..dbbcd037a5 100644 --- a/libavfilter/af_volumedetect.c +++ b/libavfilter/af_volumedetect.c @@ -20,27 +20,51 @@ #include "libavutil/channel_layout.h" #include "libavutil/avassert.h" +#include "libavutil/mem.h" #include "audio.h" #include "avfilter.h" #include "internal.h" +#define MAX_DB_FLT 1024 #define MAX_DB 91 +#define HISTOGRAM_SIZE 0x10000 +#define HISTOGRAM_SIZE_FLT (MAX_DB_FLT*2) typedef struct VolDetectContext { - /** - * Number of samples at each PCM value. - * histogram[0x8000 + i] is the number of samples at value i. - * The extra element is there for symmetry. - */ - uint64_t histogram[0x10001]; + uint64_t* histogram; ///< for integer number of samples at each PCM value, for float number of samples at each dB + uint64_t nb_samples; ///< number of samples + double sum2; ///< sum of the squares of the samples + double max; ///< maximum sample value + int is_float; ///< true if the input is in floating point } VolDetectContext; -static inline double logdb(uint64_t v) +static inline double logdb(double v, enum AVSampleFormat sample_fmt) { - double d = v / (double)(0x8000 * 0x8000); - if (!v) - return MAX_DB; - return -log10(d) * 10; + if (sample_fmt == AV_SAMPLE_FMT_FLT) { + if (!v) + return MAX_DB_FLT; + return -log10(v) * 10; + } else { + double d = v / (double)(0x8000 * 0x8000); + if (!v) + return MAX_DB; + return -log10(d) * 10; + } +} + +static void update_float_stats(VolDetectContext *vd, float *audio_data) +{ + double sample; + int idx; + if(!isnormal(*audio_data)) + return; + sample = fabsf(*audio_data); + if (sample > vd->max) + vd->max = sample; + vd->sum2 += sample * sample; + idx = lrintf(floorf(logdb(sample * sample, AV_SAMPLE_FMT_FLT))) + MAX_DB_FLT; + vd->histogram[idx]++; + vd->nb_samples++; } static int filter_frame(AVFilterLink *inlink, AVFrame *samples) @@ -51,18 +75,41 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *samples) int nb_channels = samples->ch_layout.nb_channels; int nb_planes = nb_channels; int plane, i; - int16_t *pcm; + int planar = 0; - if (!av_sample_fmt_is_planar(samples->format)) { - nb_samples *= nb_channels; + planar = av_sample_fmt_is_planar(samples->format); + if (!planar) nb_planes = 1; + if (vd->is_float) { + float *audio_data; + for (plane = 0; plane < nb_planes; plane++) { + audio_data = (float *)samples->extended_data[plane]; + for (i = 0; i < nb_samples; i++) { + if (planar) { + update_float_stats(vd, &audio_data[i]); + } else { + for (int j = 0; j < nb_channels; j++) + update_float_stats(vd, &audio_data[i * nb_channels + j]); + } + } + } + } else { + int16_t *pcm; + for (plane = 0; plane < nb_planes; plane++) { + pcm = (int16_t *)samples->extended_data[plane]; + for (i = 0; i < nb_samples; i++) { + if (planar) { + vd->histogram[pcm[i] + 0x8000]++; + vd->nb_samples++; + } else { + for (int j = 0; j < nb_channels; j++) { + vd->histogram[pcm[i * nb_channels + j] + 0x8000]++; + vd->nb_samples++; + } + } + } + } } - for (plane = 0; plane < nb_planes; plane++) { - pcm = (int16_t *)samples->extended_data[plane]; - for (i = 0; i < nb_samples; i++) - vd->histogram[pcm[i] + 0x8000]++; - } - return ff_filter_frame(inlink->dst->outputs[0], samples); } @@ -73,6 +120,20 @@ static void print_stats(AVFilterContext *ctx) uint64_t nb_samples = 0, power = 0, nb_samples_shift = 0, sum = 0; uint64_t histdb[MAX_DB + 1] = { 0 }; + if (!vd->nb_samples) + return; + if (vd->is_float) { + av_log(ctx, AV_LOG_INFO, "n_samples: %" PRId64 "\n", vd->nb_samples); + av_log(ctx, AV_LOG_INFO, "mean_volume: %.1f dB\n", -logdb(vd->sum2 / vd->nb_samples, AV_SAMPLE_FMT_FLT)); + av_log(ctx, AV_LOG_INFO, "max_volume: %.1f dB\n", -2.0*logdb(vd->max, AV_SAMPLE_FMT_FLT)); + for (i = 0; i < HISTOGRAM_SIZE_FLT && !vd->histogram[i]; i++); + for (; i >= 0 && sum < vd->nb_samples / 1000; i++) { + if (!vd->histogram[i]) + continue; + av_log(ctx, AV_LOG_INFO, "histogram_%ddb: %" PRId64 "\n", MAX_DB_FLT - i, vd->histogram[i]); + sum += vd->histogram[i]; + } + } else { for (i = 0; i < 0x10000; i++) nb_samples += vd->histogram[i]; av_log(ctx, AV_LOG_INFO, "n_samples: %"PRId64"\n", nb_samples); @@ -92,26 +153,61 @@ static void print_stats(AVFilterContext *ctx) return; power = (power + nb_samples_shift / 2) / nb_samples_shift; av_assert0(power <= 0x8000 * 0x8000); - av_log(ctx, AV_LOG_INFO, "mean_volume: %.1f dB\n", -logdb(power)); + av_log(ctx, AV_LOG_INFO, "mean_volume: %.1f dB\n", -logdb((double)power, AV_SAMPLE_FMT_S16)); max_volume = 0x8000; while (max_volume > 0 && !vd->histogram[0x8000 + max_volume] && !vd->histogram[0x8000 - max_volume]) max_volume--; - av_log(ctx, AV_LOG_INFO, "max_volume: %.1f dB\n", -logdb(max_volume * max_volume)); + av_log(ctx, AV_LOG_INFO, "max_volume: %.1f dB\n", -logdb((double)(max_volume * max_volume), AV_SAMPLE_FMT_S16)); for (i = 0; i < 0x10000; i++) - histdb[(int)logdb((i - 0x8000) * (i - 0x8000))] += vd->histogram[i]; + histdb[(int)logdb((double)(i - 0x8000) * (i - 0x8000), AV_SAMPLE_FMT_S16)] += vd->histogram[i]; for (i = 0; i <= MAX_DB && !histdb[i]; i++); for (; i <= MAX_DB && sum < nb_samples / 1000; i++) { - av_log(ctx, AV_LOG_INFO, "histogram_%ddb: %"PRId64"\n", i, histdb[i]); + av_log(ctx, AV_LOG_INFO, "histogram_%ddb: %"PRId64"\n", -i, histdb[i]); sum += histdb[i]; } + } +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + VolDetectContext *vd = ctx->priv; + size_t histogram_size; + + vd->is_float = outlink->format == AV_SAMPLE_FMT_FLT || + outlink->format == AV_SAMPLE_FMT_FLTP; + + if (!vd->is_float) { + /* + * Number of samples at each PCM value. + * Only used for integer formats. + * For 16 bit signed PCM there are 65536. + * histogram[0x8000 + i] is the number of samples at value i. + * The extra element is there for symmetry. + */ + histogram_size = HISTOGRAM_SIZE + 1; + } else { + /* + * The histogram is used to store the number of samples at each dB + * instead of the number of samples at each PCM value. + */ + histogram_size = HISTOGRAM_SIZE_FLT + 1; + } + vd->histogram = av_calloc(histogram_size, sizeof(uint64_t)); + if (!vd->histogram) + return AVERROR(ENOMEM); + return 0; } static av_cold void uninit(AVFilterContext *ctx) { + VolDetectContext *vd = ctx->priv; print_stats(ctx); + if (vd->histogram) + av_freep(&vd->histogram); } static const AVFilterPad volumedetect_inputs[] = { @@ -122,6 +218,14 @@ static const AVFilterPad volumedetect_inputs[] = { }, }; +static const AVFilterPad volumedetect_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, +}; + const AVFilter ff_af_volumedetect = { .name = "volumedetect", .description = NULL_IF_CONFIG_SMALL("Detect audio volume."), @@ -129,6 +233,9 @@ const AVFilter ff_af_volumedetect = { .uninit = uninit, .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(volumedetect_inputs), - FILTER_OUTPUTS(ff_audio_default_filterpad), - FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P), + FILTER_OUTPUTS(volumedetect_outputs), + FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_FLTP), };