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
