From patchwork Thu Jan 11 21:11:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: dmitry.gumenyuk@gmail.com X-Patchwork-Id: 7262 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.78.2 with SMTP id r2csp1130203jaa; Thu, 11 Jan 2018 13:12:06 -0800 (PST) X-Google-Smtp-Source: ACJfBotzvF7CB1oHPLuIYkOX8Ie7ubLYFbrj+vwNkUAhndP8HUoBXNnnMMcmZUvvdh/6pU1KtaCH X-Received: by 10.28.151.83 with SMTP id z80mr2043144wmd.99.1515705126176; Thu, 11 Jan 2018 13:12:06 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1515705126; cv=none; d=google.com; s=arc-20160816; b=N6RDAkkXwgdLscHOmrbrqjZIdMeKPMmRM1dBmrLJPyshBVgSO1MeU7WOSXsZDj7c1E bVV127HH9zM4ZyvPJzRlw9QYNlkdXSanJbM2FckXQFnB2g7hyGwO25ox2nCBlex0KbPR uN6WqdIAjx7JGta4Al+bptRg+ZUwCWfqjra11fLFDcQ4oocMbJtch/lDkxu10duGnIzN 9W4lVAKLfgldnED9mcx+JCp8twb7Lj/LmNtaHgRvSWuYVh8PxR7epGwOBF2a1OkQaA8V KILx4F8X4nOEogDyb8LXHwcL2UZWMTkMEV2/wr6WhA1k/DFFlMiGaTMUBxRYMihJXtWs EVxQ== 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 :arc-authentication-results; bh=oMM8ukvoN0g5f5iyyhoa47cP1z2vZS/MTjRVNIPfO2U=; b=KvjGREPta+I3og9I7ZXslNpDX+hQc9MGxz2E3BKKrGfqWhXfnMMzlFR1u6wc0WzC6b PvpKqQu3bJdUiz3CIUUakBgd97TLaL6TZCTCm4U+8B/uFmsDQZ0AbHNzri2kMGIrMAus 94Bkt6OnTNTlqxkgBL8mYofT3BmFXI9q79vJuwbiszvoP9DYTdXVGd0fZuRbddo5ZcME 8Yo4quDQtam2BDc5DjT2Rm0TTcIgw77HUP68Q84kz2Q+2pJMr2dM/gu6NQ/Eqv/kPdz6 1rqaS9yTBBhO1sUMd0QdT/5hkowSQYoQLWYW2olpv/6TGoSHcJCY90++ooamLIE2Zj2r tZPA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=Vh8E2fo/; 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=NONE 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 v127si1181359wmd.208.2018.01.11.13.12.05; Thu, 11 Jan 2018 13:12:06 -0800 (PST) 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=20161025 header.b=Vh8E2fo/; 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=NONE 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 6C50C689E31; Thu, 11 Jan 2018 23:12:02 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lf0-f54.google.com (mail-lf0-f54.google.com [209.85.215.54]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7868E689735 for ; Thu, 11 Jan 2018 23:11:55 +0200 (EET) Received: by mail-lf0-f54.google.com with SMTP id e27so3992355lfb.9 for ; Thu, 11 Jan 2018 13:11:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nP++PgbyEgeWc4rqoGzo0LRz2Z3Cg94B9MK2fUHxhK4=; b=Vh8E2fo/9+HCxRElSKnmCX2AlGiT602MxiV7WHifiDjDg+5/julJeGA9cw629cNGa5 Xj1e3UWunQRp7GAYxfjM0AzQO6MyjJ/2mgL9SmlWtDyHSmPDR7l1BNeMXVxbFqetZk1B +iWmDCXdbaVx055Z/+Q496Ahoz4I0U04vuMtwL7QcIWZylzlRKnMx1TCXbEj86i9HbgA C4vbr29k7q/FI5sGcRwUF/aIsDKTYUpaRzKHhrN8V4pIBlfS7Km/5YhsBu1N42DZi1qZ 9EiW7QraZxOT9uVBYJJwcazzh1gitM2V5NzDNVGb3tU6/2lK9UdHR1vARK7grQhYCnZ6 JZAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nP++PgbyEgeWc4rqoGzo0LRz2Z3Cg94B9MK2fUHxhK4=; b=nGOKQuAyFBx9tB3Wbh9Xnlq8SAxh4nG+T1G24w5L+pFXSA8hJ1q1AACdLepQ/Dx2gR RhoEB6+sF8rX1UodjAMiF3lEZ7E1hfdn6M26IfaNoyXBCuqKJhHUgPmaDlXKYBX08FcF XLaKxAj8uwI3qLiBpYFYNdLFX4HC1XTC4dsCKUzrOAe4JEJ8BKuHIX2y3m3NAKganx2O /eclRUQqNIef2z4O9B8FjE6hCuvFISFtuh41MNJ4csaZJ+hhkMldk0zDtt3aQJTbCNOQ HtgC2LLUwuPKVs4uH8rRUsthWNn4NeVXlo4mgFEG5OC+ikV5xUo/BCeXik6sf8gE/prB SlCg== X-Gm-Message-State: AKwxytd7rAd1aqKujTRbnbfS68ggZweyMN1IeImejzZRwfK6MfuSzPtL KRDl4esrPz+jUlrdDHszVMJT8RTl X-Received: by 10.46.97.17 with SMTP id v17mr964692ljb.70.1515705115969; Thu, 11 Jan 2018 13:11:55 -0800 (PST) Received: from localhost.localdomain ([193.25.7.30]) by smtp.gmail.com with ESMTPSA id c72sm2317563lfh.2.2018.01.11.13.11.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 11 Jan 2018 13:11:55 -0800 (PST) From: Dmytro Humeniuk To: ffmpeg-devel@ffmpeg.org Date: Thu, 11 Jan 2018 22:11:47 +0100 Message-Id: <20180111211147.11434-1-dmitry.gumenyuk@gmail.com> X-Mailer: git-send-email 2.14.3 (Apple Git-98) In-Reply-To: <20180110075805.51382-1-dmitry.gumenyuk@gmail.com> References: <20180110075805.51382-1-dmitry.gumenyuk@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2] avfilter: add dumpwave filter. X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 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: Dmytro Humeniuk Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Dmytro Humeniuk --- Changelog | 1 + doc/filters.texi | 23 +++ libavfilter/Makefile | 1 + libavfilter/af_dumpwave.c | 324 +++++++++++++++++++++++++++++++++++ libavfilter/allfilters.c | 1 + libavfilter/version.h | 4 +- tests/fate/filter-audio.mak | 13 ++ tests/ref/fate/filter-dumpwave | 1 + tests/ref/fate/filter-dumpwave-24bit | 1 + tests/ref/fate/filter-dumpwave-fltp | 1 + 10 files changed, 368 insertions(+), 2 deletions(-) create mode 100644 libavfilter/af_dumpwave.c create mode 100644 tests/ref/fate/filter-dumpwave create mode 100644 tests/ref/fate/filter-dumpwave-24bit create mode 100644 tests/ref/fate/filter-dumpwave-fltp diff --git a/Changelog b/Changelog index 61075b3392..40fd624449 100644 --- a/Changelog +++ b/Changelog @@ -38,6 +38,7 @@ version : - Removed the ffserver program - Removed the ffmenc and ffmdec muxer and demuxer - VideoToolbox HEVC encoder and hwaccel +- dumpwave audio filter version 3.4: diff --git a/doc/filters.texi b/doc/filters.texi index bd93e0ab84..1f7e4f5380 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -2538,6 +2538,29 @@ Optional. It should have a value much less than 1 (e.g. 0.05 or 0.02) and is used to prevent clipping. @end table +@section dumpwave +Dumps RMS amplitude to JSON file. +Converts samples to decibels and calculates RMS (Root-Mean-Square) audio power scaled to desired values. + +@table @option +@item s, size +Dimensions @code{WxH}. +@code{W} - number of data values in json, values will be scaled according to @code{H}. +The default value is @var{1800x140} + +@item n, nb_samples +Samples count per value per channel, default 128 + +@item f, json +Path to json file +@end table + +For example, to generate RMS amplitude for 44.1 kHz 6 seconds length audio +with dimensions @var{1800x140}, samples count @code{44100*6/1800=147} and store it to @var{/tmp/out.json}, you might use: +@example +dumpwave=s=1800x140:n=147:json=/tmp/out.json +@end example + @section dynaudnorm Dynamic Audio Normalizer. diff --git a/libavfilter/Makefile b/libavfilter/Makefile index ef4729dd3f..2ffbc9497a 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -87,6 +87,7 @@ OBJS-$(CONFIG_COMPENSATIONDELAY_FILTER) += af_compensationdelay.o OBJS-$(CONFIG_CROSSFEED_FILTER) += af_crossfeed.o OBJS-$(CONFIG_CRYSTALIZER_FILTER) += af_crystalizer.o OBJS-$(CONFIG_DCSHIFT_FILTER) += af_dcshift.o +OBJS-$(CONFIG_DUMPWAVE_FILTER) += af_dumpwave.o OBJS-$(CONFIG_DYNAUDNORM_FILTER) += af_dynaudnorm.o OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o OBJS-$(CONFIG_EBUR128_FILTER) += f_ebur128.o diff --git a/libavfilter/af_dumpwave.c b/libavfilter/af_dumpwave.c new file mode 100644 index 0000000000..486f3a0d79 --- /dev/null +++ b/libavfilter/af_dumpwave.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2017 Dmytro Humeniuk + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * waveform audio filter – dumps RMS amplitude to JSON file + */ + +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/channel_layout.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" +#include "avfilter.h" +#include "formats.h" +#include "audio.h" +#include "internal.h" + +typedef struct DumpWaveContext { + const AVClass *class; /**< class for AVOptions */ + int w; /**< number of data values in json */ + int h; /**< values will be scaled according to provided here */ + int i; /**< index of current value */ + char *json_filename; /**< json filename */ + char *str; /**< comma separated values */ + double *values; /**< scaling factors */ + int64_t nb_samples; /**< samples per value per channel */ + int64_t n; /**< current number of samples counted */ + int64_t max_samples; /**< samples per value */ + double sum; /**< sum of the squared samples per value */ + FILE *dump_fp; +} DumpWaveContext; + +#define OFFSET(x) offsetof(DumpWaveContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption dumpwave_options[] = { + { "s", "set width and height", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "1800x140"}, 0, 0, FLAGS }, + { "size", "set width and height", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "1800x140"}, 0, 0, FLAGS }, + { "n", "set number of samples per value per channel", OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 128}, 1, INT64_MAX, FLAGS }, + { "nb_samples", "set number of samples per value per channel", OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 128}, 1, INT64_MAX, FLAGS }, + { "f", "set json dump file", OFFSET(json_filename), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, + { "json", "set json dump file", OFFSET(json_filename), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(dumpwave); + +static av_cold int init(AVFilterContext *ctx) +{ + DumpWaveContext *dumpwave = ctx->priv; + + dumpwave->sum = dumpwave->i = dumpwave->n = 0; + + if (!dumpwave->json_filename) { + dumpwave->dump_fp = stdout; + } else { + dumpwave->dump_fp = fopen(dumpwave->json_filename, "w"); + if (!dumpwave->dump_fp) { + int err = AVERROR(errno); + char buf[128]; + av_strerror(err, buf, sizeof(buf)); + av_log(ctx, AV_LOG_ERROR, "Could not open json file %s: %s\n", + dumpwave->json_filename, buf); + return err; + } + } + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + DumpWaveContext *dumpwave = ctx->priv; + fclose(dumpwave->dump_fp); + av_freep(&dumpwave->str); + av_freep(&dumpwave->values); +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8P, + AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P, + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NONE + }; + AVFilterFormats *formats; + AVFilterChannelLayouts *layouts; + int ret; + + if (!(formats = ff_make_format_list(sample_fmts))) + return AVERROR(ENOMEM); + + layouts = ff_all_channel_counts(); + if (!layouts) + return AVERROR(ENOMEM); + ret = ff_set_common_channel_layouts(ctx, layouts); + if (ret < 0) + return ret; + + return ff_set_common_formats(ctx, formats); +} + +static int config_output(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + DumpWaveContext *dumpwave = ctx->priv; + const int width = dumpwave->w; + dumpwave->values = av_realloc(NULL, width * sizeof(double)); + dumpwave->str = av_realloc(NULL, width * sizeof(int)); + dumpwave->max_samples = dumpwave->nb_samples * outlink->channels; + + return 0; +} + +static int dumpwave_request_frame(AVFilterLink *outlink) +{ + AVFilterContext *ctx = outlink->src; + DumpWaveContext *dumpwave = ctx->priv; + const int width = dumpwave->w; + const int height = dumpwave->h; + char *p, *result = dumpwave->str; + + AVFilterLink *inlink = ctx->inputs[0]; + int ret; + + ret = ff_request_frame(inlink); + + if (ret == AVERROR_EOF) { + p = result; + + for(int i = 0; i < width; i++) + p += sprintf(p, "%d,", av_clip(dumpwave->h * dumpwave->values[i], 0, dumpwave->h)); + + p[-1] = '\0'; //removing trailing comma + + fprintf(dumpwave->dump_fp, "{\"width\":%d,\"height\":%d,\"samples\":[%s]}", width, height, result); + } + + return ret; +} + +/** + * Convert sample to dB and calculate root mean squared value + */ +static inline void calc_db_rms(DumpWaveContext *dumpwave, const double smpl) +{ + double s = 0.; + if (smpl != 0) + s = (20. * log10(fabs(smpl)) + 60.) / 60.; + + dumpwave->sum += s * s; + + if (dumpwave->n++ == dumpwave->max_samples) { + dumpwave->values[dumpwave->i++] = av_clipd(sqrt(dumpwave->sum / dumpwave->max_samples), 0, 1.0); + dumpwave->sum = dumpwave->n = 0; + } +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + DumpWaveContext *dumpwave = ctx->priv; + int channels = frame->channels; + int c, i; + + if (dumpwave->i < dumpwave->w) + switch (inlink->format) { + case AV_SAMPLE_FMT_DBLP: + for (c = 0; c < channels; c++) { + const double *src = (const double *)frame->extended_data[c]; + + for (i = 0; i < frame->nb_samples; i++, src++) + calc_db_rms(dumpwave, *src); + } + break; + case AV_SAMPLE_FMT_DBL: { + const double *src = (const double *)frame->extended_data[0]; + + for (i = 0; i < frame->nb_samples; i++) { + for (c = 0; c < channels; c++, src++) + calc_db_rms(dumpwave, *src); + } + + } break; + case AV_SAMPLE_FMT_FLTP: + for (c = 0; c < channels; c++) { + const float *src = (const float *)frame->extended_data[c]; + + for (i = 0; i < frame->nb_samples; i++, src++) + calc_db_rms(dumpwave, *src); + } + break; + case AV_SAMPLE_FMT_FLT: { + const float *src = (const float *)frame->extended_data[0]; + + for (i = 0; i < frame->nb_samples; i++) { + for (c = 0; c < channels; c++, src++) + calc_db_rms(dumpwave, *src); + } + + } break; + case AV_SAMPLE_FMT_S64P: + for (c = 0; c < channels; c++) { + const int64_t *src = (const int64_t *)frame->extended_data[c]; + + for (i = 0; i < frame->nb_samples; i++, src++) + calc_db_rms(dumpwave, *src / (double)INT64_MAX); + } + break; + case AV_SAMPLE_FMT_S64: { + const int64_t *src = (const int64_t *)frame->extended_data[0]; + + for (i = 0; i < frame->nb_samples; i++) { + for (c = 0; c < channels; c++, src++) + calc_db_rms(dumpwave, *src / (double)INT64_MAX); + } + + } break; + case AV_SAMPLE_FMT_S32P: + for (c = 0; c < channels; c++) { + const int32_t *src = (const int32_t *)frame->extended_data[c]; + + for (i = 0; i < frame->nb_samples; i++, src++) + calc_db_rms(dumpwave, *src / (double)INT32_MAX); + } + break; + case AV_SAMPLE_FMT_S32: { + const int32_t *src = (const int32_t *)frame->extended_data[0]; + + for (i = 0; i < frame->nb_samples; i++) { + for (c = 0; c < channels; c++, src++) + calc_db_rms(dumpwave, *src / (double)INT32_MAX); + } + + } break; + case AV_SAMPLE_FMT_S16P: + for (c = 0; c < channels; c++) { + const int16_t *src = (const int16_t *)frame->extended_data[c]; + + for (i = 0; i < frame->nb_samples; i++, src++) + calc_db_rms(dumpwave, *src / (double)INT16_MAX); + } + break; + case AV_SAMPLE_FMT_S16: { + const int16_t *src = (const int16_t *)frame->extended_data[0]; + + for (i = 0; i < frame->nb_samples; i++) { + for (c = 0; c < channels; c++, src++) + calc_db_rms(dumpwave, *src / (double)INT16_MAX); + } + + } break; + case AV_SAMPLE_FMT_U8P: + for (c = 0; c < channels; c++) { + const int8_t *src = (const int8_t *)frame->extended_data[c]; + + for (i = 0; i < frame->nb_samples; i++, src++) + calc_db_rms(dumpwave, *src / (double)INT8_MAX); + } + break; + case AV_SAMPLE_FMT_U8: { + const int8_t *src = (const int8_t *)frame->extended_data[0]; + + for (i = 0; i < frame->nb_samples; i++) { + for (c = 0; c < channels; c++, src++) + calc_db_rms(dumpwave, *src / (double)INT8_MAX); + } + + } break; + } + return ff_filter_frame(inlink->dst->outputs[0], frame); +} + +static const AVFilterPad dumpwave_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .filter_frame = filter_frame, + }, + { NULL } +}; + +static const AVFilterPad dumpwave_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .request_frame = dumpwave_request_frame, + .config_props = config_output + }, + { NULL } +}; + +AVFilter ff_af_dumpwave = { + .name = "dumpwave", + .description = NULL_IF_CONFIG_SMALL("Dump RMS amplitude to JSON file"), + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .priv_size = sizeof(DumpWaveContext), + .inputs = dumpwave_inputs, + .outputs = dumpwave_outputs, + .priv_class = &dumpwave_class, +}; diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 42516bbdf9..2539ee9e9a 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -98,6 +98,7 @@ static void register_all(void) REGISTER_FILTER(CROSSFEED, crossfeed, af); REGISTER_FILTER(CRYSTALIZER, crystalizer, af); REGISTER_FILTER(DCSHIFT, dcshift, af); + REGISTER_FILTER(DUMPWAVE, dumpwave, af); REGISTER_FILTER(DYNAUDNORM, dynaudnorm, af); REGISTER_FILTER(EARWAX, earwax, af); REGISTER_FILTER(EBUR128, ebur128, af); diff --git a/libavfilter/version.h b/libavfilter/version.h index 0f11721822..ca096962bb 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,8 +30,8 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 7 -#define LIBAVFILTER_VERSION_MINOR 11 -#define LIBAVFILTER_VERSION_MICRO 101 +#define LIBAVFILTER_VERSION_MINOR 12 +#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index bd8b3d3c35..5ed0c61593 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -340,6 +340,18 @@ fate-filter-hdcd-s32p: CMD = md5 -i $(SRC) -af hdcd -f s32le fate-filter-hdcd-s32p: CMP = oneline fate-filter-hdcd-s32p: REF = 0c5513e83eedaa10ab6fac9ddc173cf5 +FATE_AFILTER-$(call FILTERDEMDEC, DUMPWAVE, WAV, PCM_S16LE) += fate-filter-dumpwave +fate-filter-dumpwave: SRC = $(TARGET_PATH)/tests/data/asynth-44100-2.wav +fate-filter-dumpwave: CMD = ffmpeg -i $(SRC) -af dumpwave=s=1800x140:n=147:f=$(TARGET_PATH)/tests/data/fate/filter-dumpwave.out -f null - && cat $(TARGET_PATH)/tests/data/fate/filter-dumpwave.out + +FATE_AFILTER-$(call FILTERDEMDEC, DUMPWAVE, TRUEHD, TRUEHD) += fate-filter-dumpwave-fltp +fate-filter-dumpwave-fltp: SRC = $(TARGET_SAMPLES)/audiomatch/tones_afconvert_44100_stereo_aac_he2.m4a +fate-filter-dumpwave-fltp: CMD = ffmpeg -i $(SRC) -f truehd -af dumpwave=s=1800x140:n=52:f=$(TARGET_PATH)/tests/data/fate/filter-dumpwave-fltp.out -f null - && cat $(TARGET_PATH)/tests/data/fate/filter-dumpwave-fltp.out + +FATE_AFILTER-$(call FILTERDEMDEC, DUMPWAVE, FLAC, FLAC) += fate-filter-dumpwave-24bit +fate-filter-dumpwave-24bit: SRC = $(TARGET_SAMPLES)/lossless-audio/master_audio_2.0_24bit.wma +fate-filter-dumpwave-24bit: CMD = ffmpeg -i $(SRC) -f truehd -af dumpwave=s=1800x140:n=51:f=$(TARGET_PATH)/tests/data/fate/filter-dumpwave-24bit.out -f null - && cat $(TARGET_PATH)/tests/data/fate/filter-dumpwave-24bit.out + FATE_AFILTER-yes += fate-filter-formats fate-filter-formats: libavfilter/tests/formats$(EXESUF) fate-filter-formats: CMD = run libavfilter/tests/formats @@ -347,3 +359,4 @@ fate-filter-formats: CMD = run libavfilter/tests/formats FATE_SAMPLES_AVCONV += $(FATE_AFILTER_SAMPLES-yes) FATE_FFMPEG += $(FATE_AFILTER-yes) fate-afilter: $(FATE_AFILTER-yes) $(FATE_AFILTER_SAMPLES-yes) + diff --git a/tests/ref/fate/filter-dumpwave b/tests/ref/fate/filter-dumpwave new file mode 100644 index 0000000000..bd07098ef8 --- /dev/null +++ b/tests/ref/fate/filter-dumpwave @@ -0,0 +1 @@ +{"width":1800,"height":140,"samples":[103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,102,104,103,102,104,104,102,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,102,104,103,102,104,104,102,103,104,102,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,102,104,104,102,103,104,102,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,102,103,104,102,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,102,104,103,103,103,104,103,103,104,103,103,104,103,103,104,103,103,103,104,103,103,104,103,103,104,103,102,104,103,102,104,103,102,103,104,102,103,104,103,101,104,105,104,103,102,104,104,102,102,103,104,104,103,103,104,104,102,103,103,103,104,103,103,103,104,102,104,103,103,104,103,103,103,103,103,103,103,103,103,104,103,103,103,104,103,103,103,103,104,103,103,103,103,103,103,103,104,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,104,104,103,103,103,103,103,103,103,103,103,103,103,102,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,104,103,103,105,103,103,103,103,103,103,104,103,103,103,104,103,103,103,104,103,103,103,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,106,106,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,100,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,96,98,100,97,99,98,97,97,97,96,98,97,98,97,99,98,97,95,98,97,98,101,96,95,96,94,97,99,99,95,98,96,98,98,98,98,98,98,99,98,96,97,99,97,98,99,99,99,96,98,97,98,98,99,99,97,100,95,98,97,99,94,98,96,99,98,97,99,98,97,96,98,95,96,97,100,99,96,99,97,97,97,99,98,97,96,97,97,99,99,100,95,99,98,95,96,99,97,99,99,95,98,96,97,96,99,96,97,98,96,97,95,97,99,99,96,99,96,98,98,96,96,97,96,99,98,97,98,100,98,100,96,98,98,99,97,99,99,99,97,99,97,99,99,98,96,100,97,95,112,119,121,121,118,122,122,120,121,123,121,120,118,121,120,121,123,124,122,120,124,121,122,121,120,121,122,122,120,119,118,122,121,122,121,120,123,120,121,122,121,121,119,120,119,120,121,121,120,122,120,122,123,122,124,122,120,122,121,121,119,122,123,123,122,120,121,119,123,121,125,119,121,119,120,121,121,121,123,122,120,122,123,120,120,123,121,119,122,120,122,123,121,123,121,121,123,120,120,121,123,123,120,122,122,119,120,122,122,120,122,122,120,123,120,121,120,121,121,123,120,121,119,122,117,124,122,122,119,120,122,121,121,123,121,120,121,122,120,121,123,121,119,123,120,123,125,121,120,121,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,104,103,104,103,103,104,103,104,103,104,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,104,103,104,102,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,104,103,103,103,104,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,104,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,104,103,103,103,103,103,103,103,102,81,75,74,74,75,76,78,78,79,81,81,82,84,84,84,86,86,86,87,88,88,88,90,88,89,90,89,89,90,89,89,89,89,88,88,89,87,87,87,85,85,85,83,83,82,81,80,79,78,76,75,75,73,75,80,76,79,75,74,74,76,77,77,79,81,80,82,84,83,84,86,86,86,88,87,87,89,89,88,89,90,89,89,90,89,89,90,89,88,89,88,87,87,87,86,85,86,84,83,83,81,80,80,78,77,76,75,73,74,76,81,81,76,73,74,75,76,76,79,79,80,82,83,83,84,85,85,86,87,87,87,89,88,88,90,89,89,89,90,89,89,90,89,89,89,88,87,88,87,86,86,86,84,84,84,82,81,81,78,77,77,75,74,74,74,79,76,79,74,74,75,75,76,78,78,80,81,82,82,84,84,85,86,87,86,87,89,88,88,90,89,89,90,89,89,90,89,89,89,89,88,88,89,87,86,87,85,84,85,83,82,82,81,79,79,78,75,75,75,73,75,81,80,76,74,74,75,76,77,78,79,81,81,82,84,84,84,86,86,86,88,88,87,88,89,88,89,90,89,89,90,89,89,90,89,88,89,88,87,87,87,85,85,85,83,83,83,81,80,80,78,76,75,75,73,74,78,76,79,75,74,74,75,77,77,79,80,80,82,84,83,84,86,85,86,88,87,87,89,89,88,89,90,89,89,90,89,89,90,89,88,89,88,87,88,87,86,86,85,84,83,83,81,80,80,78,77,76,75,74,74,75,81,80,77,73,74,75,75,76,79,79,80,82,82,83,84,85,85,86,87,87,87,89,88,88,90,89,89,90,90,89,89,90,89,89,89,88,88,88,87,86,86,85,84,84,83,82,81,81,79,78,78,75,74,75,74,77,76,80,75,74,74,75,76,78,78,80,81,81,82,84,84,85,86,87,86,87,88,88,88,90,89,89,90,89,89,90,89,89,89,89,88,88,89,87,87,87,85,84,85,83,82,82,81,79,79,78,76,75,75,73,75,80,81,76,75,74,75,76,77,78,79,81,81,82,84,84,84,86,86,86,88,88,87,89,89,88,89,90,89,89,90,89,89,90,89,88,89,88,87,87,87,85,85,86,83,83,83,81,80,80,78,77,76,75,73,74,77,78,79,76,74,74,75,76,77,79,80,80,82,83,83,84,86,85,86,88,87,87,89,88,88,90,89,89,90,90,89,89,90,89,88,89,88,87,88,87,86,86,85,84,84,83,81,81,80,78,77,77,75,74,74,75,80,81,78,74,74,75,75,76,79,79,80,82,82,82,85,85,85,86,87,86,87,89,88,88,90,89,89,90,89,89,90,90,89,89,89,88,88,88,87,86,87,85,84,0,0,0,0,0,0,0]} diff --git a/tests/ref/fate/filter-dumpwave-24bit b/tests/ref/fate/filter-dumpwave-24bit new file mode 100644 index 0000000000..4133761201 --- /dev/null +++ b/tests/ref/fate/filter-dumpwave-24bit @@ -0,0 +1 @@ +{"width":1800,"height":140,"samples":[0,0,0,0,0,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,0,0,0,0,31,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,117,110,104,100,96,91,89,88,88,88,88,91,92,91,92,140,140,140,140,140,118,107,106,98,95,94,92,98,106,101,98,96,96,105,101,95,93,92,94,94,91,92,92,90,89,90,93,94,96,100,103,103,99,100,100,107,103,99,97,93,89,92,92,96,107,111,102,99,93,102,115,116,134,138,130,97,96,96,97,96,99,96,97,97,98,101,100,101,103,103,100,101,101,100,101,99,99,90,93,96,101,130,121,104,97,89,96,105,110,129,111,140,128,114,94,106,106,109,107,106,103,104,106,105,105,106,107,112,112,111,111,107,108,107,99,93,102,111,127,140,125,99,92,95,99,108,126,125,128,140,113,95,99,101,108,104,106,107,103,106,103,110,118,117,132,137,133,116,113,117,111,112,106,110,119,140,139,126,108,108,103,98,109,138,140,140,140,116,106,101,103,127,123,140,123,111,120,117,121,124,125,119,122,119,112,113,113,110,108,118,118,121,140,140,136,112,114,115,106,115,140,133,140,128,107,107,104,109,127,140,140,130,105,109,136,126,128,127,124,129,125,126,120,125,120,120,118,119,126,126,134,124,132,132,113,104,126,121,136,140,122,104,103,102,131,128,133,121,131,110,106,106,103,119,128,123,136,139,125,132,140,132,135,121,124,121,129,130,132,135,131,139,133,138,140,136,140,132,106,103,110,119,131,130,121,135,140,139,131,106,129,140,140,135,137,132,128,139,125,123,119,116,118,123,134,135,140,140,138,135,137,136,134,135,138,116,108,107,116,137,137,140,136,126,114,137,140,124,136,140,139,140,122,126,135,132,133,126,132,133,129,137,133,138,134,138,135,134,134,119,124,131,137,120,118,134,118,122,118,117,132,126,134,138,118,135,137,125,127,123,119,134,125,136,131,137,134,134,140,139,139,132,140,140,138,137,137,133,134,132,127,130,130,136,135,116,104,128,140,125,123,115,136,140,124,129,114,120,140,116,127,136,136,129,133,133,129,130,132,135,137,135,133,140,137,136,131,135,133,127,130,135,131,113,135,132,138,122,135,137,140,123,124,120,140,135,137,134,137,123,123,140,126,139,140,140,137,139,138,140,134,132,134,127,118,124,134,134,137,133,129,133,128,140,126,140,140,113,128,140,140,133,126,127,132,120,106,116,133,137,139,110,130,136,137,134,131,133,138,132,134,133,134,131,134,136,138,130,135,133,136,135,132,134,114,110,110,132,123,99,117,130,140,102,105,120,140,131,112,129,140,105,132,133,135,138,140,133,134,140,136,134,136,138,139,139,139,131,137,133,133,135,104,107,113,133,97,105,111,140,119,138,123,133,127,110,118,135,113,107,102,109,135,138,134,129,134,133,132,133,131,135,139,133,130,128,124,133,140,140,140,129,129,107,132,135,135,140,140,140,136,118,115,117,138,121,117,112,119,134,120,136,134,133,133,134,137,134,131,137,137,133,137,135,134,132,136,134,122,137,137,140,140,140,128,140,140,132,107,105,114,140,121,113,113,119,132,115,139,140,121,127,135,123,129,137,134,136,133,135,138,132,134,140,133,133,135,133,138,132,136,129,110,132,129,103,104,111,140,132,105,107,134,125,114,113,124,131,134,116,121,135,140,136,136,137,133,133,136,137,128,129,131,140,139,136,130,134,135,139,135,136,119,108,109,136,127,117,113,105,136,140,123,140,139,139,136,131,131,139,132,136,137,136,135,133,133,137,135,130,130,132,131,129,138,138,135,130,128,126,128,119,137,137,140,126,125,127,118,139,140,135,140,140,128,140,140,131,140,138,140,130,138,135,137,133,134,127,132,132,137,135,140,135,137,136,140,137,136,132,131,138,135,127,117,135,140,128,137,137,140,140,132,135,140,129,117,124,127,125,0,0,0,0,0,0,0,0,0,0,0]} \ No newline at end of file diff --git a/tests/ref/fate/filter-dumpwave-fltp b/tests/ref/fate/filter-dumpwave-fltp new file mode 100644 index 0000000000..6c50eb9eaf --- /dev/null +++ b/tests/ref/fate/filter-dumpwave-fltp @@ -0,0 +1 @@ +{"width":1800,"height":140,"samples":[140,140,140,140,140,120,75,61,52,51,84,89,90,91,92,96,96,100,140,140,140,140,140,130,86,62,51,44,76,86,90,94,94,95,94,96,98,100,103,102,99,101,100,101,101,103,102,101,101,100,100,101,103,102,102,100,98,101,103,101,101,100,99,101,102,103,102,100,99,100,101,103,103,102,99,100,101,101,103,102,100,101,100,101,101,102,103,100,101,100,100,100,102,104,102,100,99,102,103,101,101,99,99,101,102,104,101,99,101,99,102,101,103,102,100,101,101,101,102,102,102,101,100,103,100,102,104,102,102,100,100,101,102,104,98,101,99,102,103,102,103,99,101,102,102,104,103,101,101,101,102,101,103,102,101,102,101,101,100,103,103,101,101,101,99,102,103,103,102,99,47,41,29,99,101,100,100,102,102,104,102,99,101,100,101,102,103,102,100,80,41,38,28,33,35,31,24,26,26,25,24,23,21,21,20,21,27,21,17,22,17,23,33,32,31,28,28,26,27,27,22,20,22,20,20,19,22,18,19,17,22,26,18,21,20,20,25,19,30,27,23,28,27,33,56,47,53,63,64,72,73,33,15,23,20,22,21,25,24,27,26,25,32,44,44,49,67,64,65,79,72,72,76,77,84,76,84,79,79,76,81,79,77,80,85,80,84,85,83,82,73,76,74,79,75,89,87,80,79,83,81,81,85,80,81,81,84,78,78,85,78,78,53,53,35,64,99,102,101,100,98,101,102,103,102,99,100,100,102,82,84,67,50,37,39,90,102,100,101,99,101,101,103,102,101,100,101,100,101,103,101,102,100,100,99,102,104,102,101,100,100,101,101,105,103,99,101,100,104,102,101,99,100,101,101,103,102,100,101,101,101,100,102,104,101,101,100,100,101,102,103,102,100,100,100,102,103,104,101,99,100,101,101,103,102,100,101,101,101,103,102,100,101,100,101,102,103,102,101,100,101,99,102,104,102,101,100,99,101,102,104,102,100,100,100,102,101,103,101,99,101,101,101,102,102,102,97,102,101,103,102,101,101,100,100,101,102,102,101,101,101,99,102,103,102,101,99,100,101,101,104,101,100,100,99,102,97,74,61,56,49,43,34,22,20,94,100,102,101,102,104,102,103,102,102,102,99,62,57,47,36,35,30,19,22,18,21,25,17,20,20,27,23,38,33,28,35,41,33,39,41,46,51,44,36,25,23,26,24,15,32,23,16,27,26,28,42,44,34,41,44,40,44,44,46,46,43,39,29,49,53,43,49,55,49,63,66,75,72,84,77,82,81,55,41,42,41,39,36,58,46,43,54,57,54,59,72,72,73,79,83,83,82,79,79,82,83,83,86,78,80,82,82,77,77,84,84,91,83,75,54,38,75,75,76,80,81,80,80,82,81,77,79,82,80,77,83,88,83,68,48,40,51,90,105,99,100,106,99,98,104,100,99,103,102,99,101,104,100,100,105,53,76,100,103,100,101,104,98,99,105,99,99,106,100,98,106,101,98,105,101,98,104,101,99,102,103,100,101,103,100,100,103,101,99,104,101,99,103,101,102,99,105,100,98,104,101,98,104,102,97,103,101,98,103,103,99,102,103,99,101,104,99,101,103,99,101,103,100,101,103,100,99,102,102,99,101,104,98,101,103,101,98,103,102,98,102,104,98,102,104,98,101,105,98,101,105,99,100,104,100,100,104,101,99,101,103,99,100,105,100,99,106,101,98,105,100,98,103,105,99,101,105,98,100,105,99,99,106,100,100,104,101,100,102,102,100,101,103,100,99,102,97,82,70,73,72,71,66,62,65,60,57,51,46,42,33,89,101,98,104,101,95,85,76,70,73,70,62,65,62,58,54,48,44,36,33,26,20,22,23,26,19,19,18,40,49,41,51,55,60,73,73,72,71,78,51,23,22,16,28,21,15,23,22,42,40,50,51,54,67,76,74,71,79,81,76,81,79,81,79,83,78,76,76,79,84,82,80,80,82,77,77,78,85,84,79,77,81,80,81,82,78,72,79,79,80,90,78,82,79,77,75,82,83,83,84,76,85,80,82,82,77,79,79,85,76,55,42,24,61,95,105,101,82,81,79,81,83,77,85,79,82,79,83,79,74,48,30,38,87,97,95,100,103,105,101,100,99,100,100,104,105,100,99,100,100,101,106,103,101,99,98,107,100,98,99,103,105,101,99,99,100,101,105,104,100,98,98,100,102,106,102,100,100,100,100,103,105,101,100,99,99,101,106,104,101,99,98,100,102,106,91,103,106,102,99,99,100,101,104,104,100,99,99,100,101,106,102,101,100,99,100,102,106,102,100,99,99,102,104,105,100,98,99,100,102,106,102,100,100,109,100,100,100,100,103,105,100,99,99,99,101,106,103,101,99,98,99,103,106,102,99,99,100,102,103,105,100,99,99,99,101,106,103,101,100,99,99,102,96,100,102,106,101,100,99,99,101,106,104,101,99,98,100,102,106,102,99,99,94,65,32,43,44,51,50,48,45,42,40,40,30,22,21,22,20,22,18,88,83,33,27,40,45,46,50,43,39,42,46,35,30,24,18,19,18,23,18,17,21,28,31,36,37,23,26,26,35,41,55,59,76,59,66,71,73,75,49,19,20,34,36,34,33,23,27,33,39,39,57,68,66,63,60,68,72,81,81,82,83,78,75,80,84,90,79,85,81,81,83,83,83,81,78,86,80,76,87,83,87,82,82,84,87,80,79,84,82,82,86,85,86,81,73,89,80,78,82,80,81,85,84,83,58,46,48,55,94,101,101,101,103,103,101,100,84,78,83,78,79,80,76,76,48,50,33,81,98,100,102,102,104,102,99,101,100,101,102,103,101,101,101,101,100,102,103,101,102,100,100,100,102,104,101,100,99,102,103,102,102,100,100,100,102,104,102,101,99,100,101,101,103,102,100,101,100,102,101,103,102,101,101,101,100,101,103,102,102,100,100,99,102,104,103,100,99,102,103,103,102,99,100,100,102,102,103,101,100,100,101,100,102,102,101,101,100,101,100,102,104,101,101,100,99,101,102,104,102,100,99,100,102,104,101,99,100,101,101,104,102,99,101,100,102,101,103,102,100,101,100,100,101,103,102,102,100,101,99,102,104,102,102,100,99,101,102,104,89,47,31,27,78,103,101,99,101,101,101,103,102,100,101,100,101,101,102,99,72,36,26,26,29,27,22,23,22,21,19,18,22,28,25,20,26,21,24,37,34,50,41,33,30,18,21,23,22,18,29,20,29,21,26,22,17,29,33,35,43,32,32,43,39,35,51,36,34,36,57,53,69,58,72,74,77,77,79,81,76,78,60,46,33,46,45,28,37,53,52,61,58,59,79,81,77,77,81,76,76,82,84,81,81,77,79,77,79,82,81,87,83,80,80,84,80,80,79,80,85,82,87,80,80,77,78,78,80,86,80,81,82,82,81,85,83,81,76,79,86,83,82,61,46,34,43,89,99,100,101,100,100,102,102,101,101,104,101,102,87,78,77,52,36,39,68,97,103,101,101,103,101,101,101,102,100,101,100,100,100,101,102,100,101,102,101,101,103,102,102,101,103,101,101,102,102,100,101,97,102,101,102,102,101,100,103,100,100,100,101,101,100,103,100,101,102,103,100,102,102,102,100,103,102,101,101,103,100,100,101,100,100,100,102,100,100,102,109,100,99,100,101,100,102,102,101,100,103,101,101,102,103,101,101,103,101,100,102,101,100,100,100,100,100,102,102,101,101,103,101,101,103,102,101,101,103,91,101,101,103,101,101,103,102,101,102,102,101,100,102,100,100,100,101,101,100,103,101,101,102,103,101,102,103,102,100,95,60,32,30,28,31,31,21,16,82,102,102,101,100,101,101,99,100,101,101,83,45,30,27,33,25,29,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]} \ No newline at end of file