From patchwork Tue Jun 2 18:35:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Nicolas George X-Patchwork-Id: 20128 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 8EE2344B1DA for ; Tue, 2 Jun 2020 21:35:16 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 52EA168A7B8; Tue, 2 Jun 2020 21:35:16 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from nef.ens.fr (nef2.ens.fr [129.199.96.40]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 374E0680D13 for ; Tue, 2 Jun 2020 21:35:10 +0300 (EEST) X-ENS-nef-client: 129.199.129.80 Received: from phare.normalesup.org (phare.normalesup.org [129.199.129.80]) by nef.ens.fr (8.14.4/1.01.28121999) with ESMTP id 052IZ9rU023809 for ; Tue, 2 Jun 2020 20:35:09 +0200 Received: by phare.normalesup.org (Postfix, from userid 1001) id 2DE0DE0633; Tue, 2 Jun 2020 20:35:09 +0200 (CEST) From: Nicolas George To: ffmpeg-devel@ffmpeg.org Date: Tue, 2 Jun 2020 20:35:04 +0200 Message-Id: <20200602183506.491783-1-george@nsup.org> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.4.3 (nef.ens.fr [129.199.96.32]); Tue, 02 Jun 2020 20:35:09 +0200 (CEST) Subject: [FFmpeg-devel] [PATCH 1/3] lavfi/asrc_sine: move sine table generation to a separate file. 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Nicolas George --- libavfilter/Makefile | 2 +- libavfilter/asrc_sine.c | 53 ++++----------------------------- libavfilter/intsine.c | 65 +++++++++++++++++++++++++++++++++++++++++ libavfilter/intsine.h | 44 ++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 49 deletions(-) create mode 100644 libavfilter/intsine.c create mode 100644 libavfilter/intsine.h diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 5123540653..83d939f0b1 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -151,7 +151,7 @@ OBJS-$(CONFIG_ANULLSRC_FILTER) += asrc_anullsrc.o OBJS-$(CONFIG_FLITE_FILTER) += asrc_flite.o OBJS-$(CONFIG_HILBERT_FILTER) += asrc_hilbert.o OBJS-$(CONFIG_SINC_FILTER) += asrc_sinc.o -OBJS-$(CONFIG_SINE_FILTER) += asrc_sine.o +OBJS-$(CONFIG_SINE_FILTER) += asrc_sine.o intsine.o OBJS-$(CONFIG_ANULLSINK_FILTER) += asink_anullsink.o diff --git a/libavfilter/asrc_sine.c b/libavfilter/asrc_sine.c index 3a87210b4b..8fff1dda8b 100644 --- a/libavfilter/asrc_sine.c +++ b/libavfilter/asrc_sine.c @@ -27,6 +27,7 @@ #include "audio.h" #include "avfilter.h" #include "internal.h" +#include "intsine.h" typedef struct SineContext { const AVClass *class; @@ -81,50 +82,6 @@ static const AVOption sine_options[] = { AVFILTER_DEFINE_CLASS(sine); -#define LOG_PERIOD 15 -#define AMPLITUDE 4095 -#define AMPLITUDE_SHIFT 3 - -static void make_sin_table(int16_t *sin) -{ - unsigned half_pi = 1 << (LOG_PERIOD - 2); - unsigned ampls = AMPLITUDE << AMPLITUDE_SHIFT; - uint64_t unit2 = (uint64_t)(ampls * ampls) << 32; - unsigned step, i, c, s, k, new_k, n2; - - /* Principle: if u = exp(i*a1) and v = exp(i*a2), then - exp(i*(a1+a2)/2) = (u+v) / length(u+v) */ - sin[0] = 0; - sin[half_pi] = ampls; - for (step = half_pi; step > 1; step /= 2) { - /* k = (1 << 16) * amplitude / length(u+v) - In exact values, k is constant at a given step */ - k = 0x10000; - for (i = 0; i < half_pi / 2; i += step) { - s = sin[i] + sin[i + step]; - c = sin[half_pi - i] + sin[half_pi - i - step]; - n2 = s * s + c * c; - /* Newton's method to solve n² * k² = unit² */ - while (1) { - new_k = (k + unit2 / ((uint64_t)k * n2) + 1) >> 1; - if (k == new_k) - break; - k = new_k; - } - sin[i + step / 2] = (k * s + 0x7FFF) >> 16; - sin[half_pi - i - step / 2] = (k * c + 0x8000) >> 16; - } - } - /* Unshift amplitude */ - for (i = 0; i <= half_pi; i++) - sin[i] = (sin[i] + (1 << (AMPLITUDE_SHIFT - 1))) >> AMPLITUDE_SHIFT; - /* Use symmetries to fill the other three quarters */ - for (i = 0; i < half_pi; i++) - sin[half_pi * 2 - i] = sin[i]; - for (i = 0; i < 2 * half_pi; i++) - sin[i + 2 * half_pi] = -sin[i]; -} - static const char *const var_names[] = { "n", "pts", @@ -146,10 +103,10 @@ static av_cold int init(AVFilterContext *ctx) int ret; SineContext *sine = ctx->priv; - if (!(sine->sin = av_malloc(sizeof(*sine->sin) << LOG_PERIOD))) + if (!(sine->sin = av_malloc(sizeof(*sine->sin) << SINE_LOG_PERIOD))) return AVERROR(ENOMEM); sine->dphi = ldexp(sine->frequency, 32) / sine->sample_rate + 0.5; - make_sin_table(sine->sin); + ff_make_sin_table(sine->sin); if (sine->beep_factor) { sine->beep_period = sine->sample_rate; @@ -244,10 +201,10 @@ static int request_frame(AVFilterLink *outlink) samples = (int16_t *)frame->data[0]; for (i = 0; i < nb_samples; i++) { - samples[i] = sine->sin[sine->phi >> (32 - LOG_PERIOD)]; + samples[i] = sine->sin[sine->phi >> (32 - SINE_LOG_PERIOD)]; sine->phi += sine->dphi; if (sine->beep_index < sine->beep_length) { - samples[i] += sine->sin[sine->phi_beep >> (32 - LOG_PERIOD)] << 1; + samples[i] += sine->sin[sine->phi_beep >> (32 - SINE_LOG_PERIOD)] << 1; sine->phi_beep += sine->dphi_beep; } if (++sine->beep_index == sine->beep_period) diff --git a/libavfilter/intsine.c b/libavfilter/intsine.c new file mode 100644 index 0000000000..ad99dc0147 --- /dev/null +++ b/libavfilter/intsine.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020 Nicolas George + * + * 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 + */ + +#include "intsine.h" + +#define AMPLITUDE_SHIFT 3 + +void ff_make_sin_table(int16_t *sin) +{ + unsigned half_pi = 1 << (SINE_LOG_PERIOD - 2); + unsigned ampls = SINE_AMPLITUDE << AMPLITUDE_SHIFT; + uint64_t unit2 = (uint64_t)(ampls * ampls) << 32; + unsigned step, i, c, s, k, new_k, n2; + + /* Principle: if u = exp(i*a1) and v = exp(i*a2), then + exp(i*(a1+a2)/2) = (u+v) / length(u+v) */ + sin[0] = 0; + sin[half_pi] = ampls; + for (step = half_pi; step > 1; step /= 2) { + /* k = (1 << 16) * amplitude / length(u+v) + In exact values, k is constant at a given step */ + k = 0x10000; + for (i = 0; i < half_pi / 2; i += step) { + s = sin[i] + sin[i + step]; + c = sin[half_pi - i] + sin[half_pi - i - step]; + n2 = s * s + c * c; + /* Newton's method to solve n² * k² = unit² */ + while (1) { + new_k = (k + unit2 / ((uint64_t)k * n2) + 1) >> 1; + if (k == new_k) + break; + k = new_k; + } + sin[i + step / 2] = (k * s + 0x7FFF) >> 16; + sin[half_pi - i - step / 2] = (k * c + 0x8000) >> 16; + } + } + /* Unshift amplitude */ + for (i = 0; i <= half_pi; i++) + sin[i] = (sin[i] + (1 << (AMPLITUDE_SHIFT - 1))) >> AMPLITUDE_SHIFT; + /* Use symmetries to fill the other three quarters */ + for (i = 0; i < half_pi; i++) + sin[half_pi * 2 - i] = sin[i]; + for (i = 0; i < 2 * half_pi; i++) + sin[i + 2 * half_pi] = -sin[i]; +} + + diff --git a/libavfilter/intsine.h b/libavfilter/intsine.h new file mode 100644 index 0000000000..0723a9f141 --- /dev/null +++ b/libavfilter/intsine.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020 Nicolas George + * + * 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 + */ + +#ifndef AVFILTER_INTSINE_H +#define AVFILTER_INTSINE_H + +#include + +/** + * Make a sin() table with integer arithmetic. + * + * The provided pointer must point to an array of SINE_PERIOD. + * It will be filled with one period ([0,2π[) of sine values with amplitude + * SINE_AMPLITUDE. + * + * A good way to use this table is to use a phase variable phi of type + * uint32_t, with 0 for 0 and 1<<32 for 2π and access the table at + * sin[phi >> SINE_SHIFT_PHI]. + */ +void ff_make_sin_table(int16_t *sin); + +#define SINE_LOG_PERIOD 15 +#define SINE_PERIOD (1U<