[FFmpeg-devel] [PATCH 1/3] lavfi/asrc_sine: move sine table generation to a separate file.
Nicolas George
george at nsup.org
Tue Jun 2 21:35:04 EEST 2020
Signed-off-by: Nicolas George <george at nsup.org>
---
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 <stdint.h>
+
+/**
+ * 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<<SINE_LOG_PERIOD)
+#define SINE_AMPLITUDE 4095
+#define SINE_SHIFT_PHI (32 - SINE_LOG_PERIOD)
+
+#endif
--
2.26.2
More information about the ffmpeg-devel
mailing list