diff mbox series

[FFmpeg-devel,PATCHv2,GSoC] audio filter-use cellular automata to generate tones

Message ID 20200326080511.32555-1-ashutoshp012345@gmail.com
State New
Headers show
Series [FFmpeg-devel,PATCHv2,GSoC] audio filter-use cellular automata to generate tones | expand

Checks

Context Check Description
andriy/ffmpeg-patchwork warning Failed to apply patch

Commit Message

Ashutosh Pradhan March 26, 2020, 8:05 a.m. UTC
Use cellular automata and fluidsynth sequencer to generate tones in major pentatonic scale

Comments

Nicolas George March 26, 2020, 9:11 a.m. UTC | #1
Ashutosh Pradhan (12020-03-26):
> Use cellular automata and fluidsynth sequencer to generate tones in major pentatonic scale

Can you explain the use cases for this filter?

Regards,
Ashutosh Pradhan March 26, 2020, 9:21 a.m. UTC | #2
I was trying to random tones using cellular automata (it won't sound good
if the tones are too random so I used a scale) for the GSoC audio tones
filter project.

On Thu, Mar 26, 2020 at 2:41 PM Nicolas George <george@nsup.org> wrote:

> Ashutosh Pradhan (12020-03-26):
> > Use cellular automata and fluidsynth sequencer to generate tones in
> major pentatonic scale
>
> Can you explain the use cases for this filter?
>
> Regards,
>
> --
>   Nicolas George
>
Nicolas George March 26, 2020, 9:23 a.m. UTC | #3
Ashutosh Pradhan (12020-03-26):
> I was trying to random tones using cellular automata (it won't sound good
> if the tones are too random so I used a scale) for the GSoC audio tones
> filter project.

Yes, that's already in the doc. What I ask is what good you expect from
it.

> On Thu, Mar 26, 2020 at 2:41 PM Nicolas George <george@nsup.org> wrote:

Please remember not to top post on this mailing-list.

Regards,
Ashutosh Pradhan March 26, 2020, 9:48 a.m. UTC | #4
On Thu, Mar 26, 2020 at 2:53 PM Nicolas George <george@nsup.org> wrote:

> Ashutosh Pradhan (12020-03-26):
> > I was trying to random tones using cellular automata (it won't sound good
> > if the tones are too random so I used a scale) for the GSoC audio tones
> > filter project.
>
> Yes, that's already in the doc. What I ask is what good you expect from
> it.
> Since random tones generated using seed( ) was already sent on the mailing
> list, Paul had suggested me to control the duration between tones and to
> generate tones using cellular automata.
> > On Thu, Mar 26, 2020 at 2:41 PM Nicolas George <george@nsup.org> wrote:
>
> Please remember not to top post on this mailing-list.
>
> Regards,
>
> --
>   Nicolas George
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Paul B Mahol March 26, 2020, 9:48 a.m. UTC | #5
On 3/26/20, Nicolas George <george@nsup.org> wrote:
> Ashutosh Pradhan (12020-03-26):
>> I was trying to random tones using cellular automata (it won't sound good
>> if the tones are too random so I used a scale) for the GSoC audio tones
>> filter project.
>
> Yes, that's already in the doc. What I ask is what good you expect from
> it.

What kind of insinuation is this?
This is qualification task for GSoC project, if you have something against it,
ask me directly instead.

>
>> On Thu, Mar 26, 2020 at 2:41 PM Nicolas George <george@nsup.org> wrote:
>
> Please remember not to top post on this mailing-list.
>
> Regards,
>
> --
>   Nicolas George
>
Nicolas George March 26, 2020, 9:51 a.m. UTC | #6
Paul B Mahol (12020-03-26):
> What kind of insinuation is this?

No insinuation at all, just an honest question.

> This is qualification task for GSoC project, if you have something against it,
> ask me directly instead.

Of course, feel free to answer the question. What is the use case for
this filter?
Nicolas George March 26, 2020, 9:52 a.m. UTC | #7
Ashutosh Pradhan (12020-03-26):
> Since random tones generated using seed( ) was already sent on the mailing
> list, Paul had suggested me to control the duration between tones and to
> generate tones using cellular automata.

I am not asking what YOU are doing, I am asking what benefits our users
would get from this filter. In what case a user would want to use this
filter.

If you cannot answer this question, then there is no reason to adopt it.

Regards,
Paul B Mahol March 26, 2020, 10 a.m. UTC | #8
On 3/26/20, Nicolas George <george@nsup.org> wrote:
> Paul B Mahol (12020-03-26):
>> What kind of insinuation is this?
>
> No insinuation at all, just an honest question.

We will see...

>
>> This is qualification task for GSoC project, if you have something against
>> it,
>> ask me directly instead.
>
> Of course, feel free to answer the question. What is the use case for
> this filter?

Use case is to generate nice listenable music that is computer generated.
This filter as is just prototype and is not meant to be applied in
current version
but only when final version is done with all needed features is implemented.
Nicolas George March 26, 2020, 10:04 a.m. UTC | #9
Paul B Mahol (12020-03-26):
> > No insinuation at all, just an honest question.
> We will see...

This... is an insinuation.

> Use case is to generate nice listenable music that is computer generated.
> This filter as is just prototype and is not meant to be applied in
> current version but only when final version is done with all needed
> features is implemented.

Ok. I doubt it will achieve anything without incorporating the rules of
harmony discovered during the renaissance, but as long as the goal is
properly defined I have no objection.

I had doubts that it was meant for testing, because it is similar to an
old proposal of mine which was exactly meant for testing. This
implementation is 100% unsuited for testing since it uses an external
library.

Regards,
Paul B Mahol March 26, 2020, 10:09 a.m. UTC | #10
On 3/26/20, Nicolas George <george@nsup.org> wrote:
> Paul B Mahol (12020-03-26):
>> > No insinuation at all, just an honest question.
>> We will see...
>
> This... is an insinuation.
>
>> Use case is to generate nice listenable music that is computer generated.
>> This filter as is just prototype and is not meant to be applied in
>> current version but only when final version is done with all needed
>> features is implemented.
>
> Ok. I doubt it will achieve anything without incorporating the rules of
> harmony discovered during the renaissance, but as long as the goal is
> properly defined I have no objection.
>
> I had doubts that it was meant for testing, because it is similar to an
> old proposal of mine which was exactly meant for testing. This
> implementation is 100% unsuited for testing since it uses an external
> library.

That is just your biased opinion.
Nicolas George March 26, 2020, 10:12 a.m. UTC | #11
Paul B Mahol (12020-03-26):
> That is just your biased opinion.

No, that is not my opinion, that is the position of the project for
years: we don't control external libraries, their output can change from
one version to the next or with forks and patched versions. Only
internal implementation is suited for testing, preferably bit-exact.
Paul B Mahol March 26, 2020, 10:16 a.m. UTC | #12
On 3/26/20, Nicolas George <george@nsup.org> wrote:
> Paul B Mahol (12020-03-26):
>> That is just your biased opinion.
>
> No, that is not my opinion, that is the position of the project for
> years: we don't control external libraries, their output can change from
> one version to the next or with forks and patched versions. Only
> internal implementation is suited for testing, preferably bit-exact.
>

Apparently you are talking about completely different and irrelevant stuff
for this task.
Nicolas George March 26, 2020, 10:24 a.m. UTC | #13
Paul B Mahol (12020-03-26):
> Apparently you are talking about completely different and irrelevant stuff
> for this task.

Apparently, you did not read my previous mails very carefully, because I
already explained.
Thilo Borgmann March 26, 2020, 10:26 a.m. UTC | #14
Am 26.03.20 um 11:24 schrieb Nicolas George:
> Paul B Mahol (12020-03-26):
>> Apparently you are talking about completely different and irrelevant stuff
>> for this task.
> 
> Apparently, you did not read my previous mails very carefully, because I
> already explained.

Please let's stop here, we're loosing the connection to the subject.

-Thilo
Thilo Borgmann March 26, 2020, 10:29 a.m. UTC | #15
Am 26.03.20 um 10:48 schrieb Paul B Mahol:
> On 3/26/20, Nicolas George <george@nsup.org> wrote:
>> Ashutosh Pradhan (12020-03-26):
>>> I was trying to random tones using cellular automata (it won't sound good
>>> if the tones are too random so I used a scale) for the GSoC audio tones
>>> filter project.
>>
>> Yes, that's already in the doc. What I ask is what good you expect from
>> it.
> 
> What kind of insinuation is this?
> This is qualification task for GSoC project, if you have something against it,
> ask me directly instead.

Let's look at this. There are two things here:

a) Is it a good enough solution of the qualfification task Paul has given to Ashutosh?

b) Is it unsuitable to apply? Well that might be but we need to get clear about a) for the sake of GSoC.

Also, a) & b) might be a reoccuring problem this year, as IIRC Jai also gave a qualification tasks that might be on its own useless to apply to git HEAD. But AFAIKT this is not on devel by now. So please let's concentrate on these two questions. Any thoughts appreciated.

Thanks,
Thilo
Nicolas George March 26, 2020, 10:58 a.m. UTC | #16
Thilo Borgmann (12020-03-26):
> Let's look at this. There are two things here:
> 
> a) Is it a good enough solution of the qualfification task Paul has
> given to Ashutosh?
> 
> b) Is it unsuitable to apply? Well that might be but we need to get
> clear about a) for the sake of GSoC.
> 
> Also, a) & b) might be a reoccuring problem this year, as IIRC Jai
> also gave a qualification tasks that might be on its own useless to
> apply to git HEAD. But AFAIKT this is not on devel by now. So please
> let's concentrate on these two questions. Any thoughts appreciated.

The original proposal for a tone audio source was from me, more than a
year ago. It was for testing purposes: to be able to feed filters and
codecs realistic input without relying on external files. For that, it
would have been completely internal and bit-exact.

Now, there is a new proposal. Without looking into it closer, I supposed
it was based on the same goal: testing. Apparently not. But I have not
seen that discussed on the list.

I have no objection to the task if it serves a purpose. But it has
nothing to do with my original proposal and this version, using an
external library, would be worthless for testing.

Regards,
Thilo Borgmann March 26, 2020, 11:11 a.m. UTC | #17
Am 26.03.20 um 11:58 schrieb Nicolas George:
> Thilo Borgmann (12020-03-26):
>> Let's look at this. There are two things here:
>>
>> a) Is it a good enough solution of the qualfification task Paul has
>> given to Ashutosh?
>>
>> b) Is it unsuitable to apply? Well that might be but we need to get
>> clear about a) for the sake of GSoC.
>>
>> Also, a) & b) might be a reoccuring problem this year, as IIRC Jai
>> also gave a qualification tasks that might be on its own useless to
>> apply to git HEAD. But AFAIKT this is not on devel by now. So please
>> let's concentrate on these two questions. Any thoughts appreciated.
> 
> The original proposal for a tone audio source was from me, more than a
> year ago. It was for testing purposes: to be able to feed filters and
> codecs realistic input without relying on external files. For that, it
> would have been completely internal and bit-exact.
> 
> Now, there is a new proposal. Without looking into it closer, I supposed
> it was based on the same goal: testing. Apparently not. But I have not
> seen that discussed on the list.
> 
> I have no objection to the task if it serves a purpose. But it has
> nothing to do with my original proposal and this version, using an
> external library, would be worthless for testing.

Ok. So if I understand all of this correctly, the overall goal of the tones project is already redundant to your old proposal (or at least partially, Paul?).

Has there been any reason why it never made it into git HEAD?

So for this patch as-is, AFAICT Paul wanted the external lib as qualification task only and finally get things natively implemented during GSoC?

If so, we can first review this patch as RFC to give Ashutosh feedback to his coding & things. And wether or not he'll pass qualification, gets selected for a probably available slot etc, reads as if he's doing the GSoC project finally, we can have Ashutosh work on an implementation of the audio tones project. Assuming there haven't been any fundamental objections to Nicolas old proposal about such a thing already.

And then, it would of course only make sense to do this project based on what Nicolas old proposal was. Assuming it served the same goal.

Nicolas, can you please give a link here to your proposal for Ashutosh to find it easily?

-Thilo
Nicolas George March 26, 2020, 11:18 a.m. UTC | #18
Thilo Borgmann (12020-03-26):
> Ok. So if I understand all of this correctly, the overall goal of the
> tones project is already redundant to your old proposal (or at least
> partially, Paul?).

I do not know what the overall goal of the tones project is: I have not
seen it discussed on the list.

> Has there been any reason why it never made it into git HEAD?

It was just a vague proposal, not actual code.

> So for this patch as-is, AFAICT Paul wanted the external lib as
> qualification task only and finally get things natively implemented
> during GSoC?

I don't know what Paul wanted, I have not seen it discussed on the list.

> And then, it would of course only make sense to do this project based
> on what Nicolas old proposal was. Assuming it served the same goal.
> 
> Nicolas, can you please give a link here to your proposal for Ashutosh
> to find it easily?

https://ffmpeg.org/pipermail/ffmpeg-devel/2018-September/234714.html

Regards,
Thilo Borgmann March 26, 2020, 4:14 p.m. UTC | #19
Am 26.03.20 um 12:18 schrieb Nicolas George:
> Thilo Borgmann (12020-03-26):
>> Ok. So if I understand all of this correctly, the overall goal of the
>> tones project is already redundant to your old proposal (or at least
>> partially, Paul?).
> 
> I do not know what the overall goal of the tones project is: I have not
> seen it discussed on the list.

I strongly agree we should more thoroughly review future project proposals. The questions about validity/usefullness raised here should have been settled before it goes online for students to select.


>> Has there been any reason why it never made it into git HEAD?
> 
> It was just a vague proposal, not actual code.
> 
>> So for this patch as-is, AFAICT Paul wanted the external lib as
>> qualification task only and finally get things natively implemented
>> during GSoC?
> 
> I don't know what Paul wanted, I have not seen it discussed on the list.
> 
>> And then, it would of course only make sense to do this project based
>> on what Nicolas old proposal was. Assuming it served the same goal.

That was basically my misunderstanding of the topic. Paul wants a tone/music generator utilizing fluidsynth, not just as part of qualification as I understood it. And after talking to Nicolas, he is fine continuing that GSoC project as intended.

@Ashutosh: So please continue working on your project/application with Paul as planned. 

Time to give some actual feedback on the code / review, please.

Thanks,
Thilo
diff mbox series

Patch

diff --git a/Changelog b/Changelog
index d1572553a5..5ddd2484b0 100644
--- a/Changelog
+++ b/Changelog
@@ -48,6 +48,7 @@  version <next>:
 - AMQP 0-9-1 protocol (RabbitMQ)
 - Vulkan support
 - avgblur_vulkan, overlay_vulkan, scale_vulkan and chromaber_vulkan filters
+- atone filter
 
 
 version 4.2:
diff --git a/configure b/configure
index 6ceb0c7af4..2ec7e377f3 100755
--- a/configure
+++ b/configure
@@ -233,6 +233,7 @@  External library support:
                            and libraw1394 [no]
   --enable-libfdk-aac      enable AAC de/encoding via libfdk-aac [no]
   --enable-libflite        enable flite (voice synthesis) support via libflite [no]
+  --enable-libfluidsynth   enable libfluidsynth support for fluidsynth [no]
   --enable-libfontconfig   enable libfontconfig, useful for drawtext filter [no]
   --enable-libfreetype     enable libfreetype, needed for drawtext filter [no]
   --enable-libfribidi      enable libfribidi, improves drawtext filter [no]
@@ -1770,6 +1771,7 @@  EXTERNAL_LIBRARY_LIST="
     libdc1394
     libdrm
     libflite
+    libfluidsynth
     libfontconfig
     libfreetype
     libfribidi
@@ -3465,6 +3467,7 @@  asr_filter_deps="pocketsphinx"
 ass_filter_deps="libass"
 atempo_filter_deps="avcodec"
 atempo_filter_select="rdft"
+atone_filter_deps="libfluidsynth"
 avgblur_opencl_filter_deps="opencl"
 avgblur_vulkan_filter_deps="vulkan libglslang"
 azmq_filter_deps="libzmq"
@@ -6270,6 +6273,7 @@  enabled libfdk_aac        && { check_pkg_config libfdk_aac fdk-aac "fdk-aac/aace
                                  warn "using libfdk without pkg-config"; } }
 flite_extralibs="-lflite_cmu_time_awb -lflite_cmu_us_awb -lflite_cmu_us_kal -lflite_cmu_us_kal16 -lflite_cmu_us_rms -lflite_cmu_us_slt -lflite_usenglish -lflite_cmulex -lflite"
 enabled libflite          && require libflite "flite/flite.h" flite_init $flite_extralibs
+enabled libfluidsynth     && require_pkg_config libfluidsynth fluidsynth "fluidsynth.h" fluid_log
 enabled fontconfig        && enable libfontconfig
 enabled libfontconfig     && require_pkg_config libfontconfig fontconfig "fontconfig/fontconfig.h" FcInit
 enabled libfreetype       && require_pkg_config libfreetype freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType
diff --git a/doc/filters.texi b/doc/filters.texi
index 328e984e92..193dcaf8e9 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -6050,6 +6050,60 @@  anoisesrc=d=60:c=pink:r=44100:a=0.5
 @end example
 @end itemize
 
+@section atone
+
+Generate legato tones using cellular automata.
+To compile filter configure ffmpeg with @code{--enable-libfluidsynth} 
+
+The filter accepts the following options:
+
+@table @option
+@item sample_rate, r
+Specify the sample rate. Default value is 44100 Hz.
+
+@item sfont
+Specify the location of soundfont file. Default value is 
+"/usr/share/sounds/sf2/FluidR3_GM.sf2"(for linux).
+
+@item duration, d
+Specify the duration of the generated audio stream. Not specifying this option
+results in playing tones for infinite length.
+
+@item velocity, v
+Specify the velocity of key press. Default value is 80.
+
+@item MIDI_channel
+Specify the MIDI channel number between(0 to 16) to play tones. Default is 0.
+
+@item tone_change_interval, t
+Specify the time interval between successive tones in seconds. Default is 0.2s.
+
+@item rule
+Specify the rule between 0 to 255 to get the rule set. Default is 30.
+
+@item width
+Specify the width of the cells array. Default is 64.
+
+@item tempo
+Specify the beats per minute. Default is 120.
+
+@item samples_per_frame
+Set the number of samples per each output frame. Default is 1024.
+@end table
+
+@subsection Examples
+
+@itemize
+
+@item
+Generate 10 seconds of random tones, with a key velocity of 100, midi channel 1
+and an tone change interval of 0.1s:
+@example
+atone=d=10:MIDI_channel=1:v=100:t=0.1:sfont="example.sf2":rule=193
+atone=duration=10:MIDI_channel=1:velocity=100:tone_change_interval=0.1:sfont="example.sf2":rule=193
+@end example
+@end itemize
+
 @section hilbert
 
 Generate odd-tap Hilbert transform FIR coefficients.
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 750412da6b..b1f0c4be35 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -151,6 +151,7 @@  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_ATONE_FILTER)                  += asrc_atone.o
 
 OBJS-$(CONFIG_ANULLSINK_FILTER)              += asink_anullsink.o
 
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 501e5d041b..4d3efc7e15 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -145,6 +145,7 @@  extern AVFilter ff_asrc_flite;
 extern AVFilter ff_asrc_hilbert;
 extern AVFilter ff_asrc_sinc;
 extern AVFilter ff_asrc_sine;
+extern AVFilter ff_asrc_atone;
 
 extern AVFilter ff_asink_anullsink;
 
diff --git a/libavfilter/asrc_atone.c b/libavfilter/asrc_atone.c
new file mode 100644
index 0000000000..79643a15ec
--- /dev/null
+++ b/libavfilter/asrc_atone.c
@@ -0,0 +1,365 @@ 
+/*
+ * 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 <float.h>
+#include <stdio.h>
+#include <string.h>
+#include <fluidsynth.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/eval.h"
+#include "libavutil/opt.h"
+#include "libavutil/lfg.h"
+#include "libavutil/random_seed.h"
+#include "audio.h"
+#include "avfilter.h"
+#include "internal.h"
+
+typedef struct AtoneContext
+{
+    const AVClass* class;
+    int64_t duration;
+    int nb_samples;
+    int sample_rate;
+    int64_t pts;
+    int infinite;
+
+    fluid_settings_t* settings;
+    fluid_synth_t* synth;
+    fluid_sequencer_t *sequencer;
+    short synth_destination, client_destination;
+    unsigned int beat_dur;
+    unsigned int tempo;
+    unsigned int time_marker;
+    unsigned int pattern_size;
+    char* sfont;                      ///< soundfont file
+    int sfont_id;
+    int midi_chan;                   ///< midi channel number
+    int velocity;                   ///< velocity of key
+    double changerate;              ///< get the time interval of changing tones
+    int notes[5];
+    int *cells;
+    int *nextgen;
+    int rule;                       ///< Rule for changing value in cell(taking 3 cells at time hence 2^8 rules possible)
+    int width;                      ///< width of the cell array
+    int ruleset[8];                 ///< taking 3 cells at a time
+    int framecount;
+}AtoneContext;
+
+#define CONTEXT AtoneContext
+#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+
+#define OPT_GENERIC(name, field, def, min, max, descr, type, deffield, ...) \
+    { name, descr, offsetof(CONTEXT, field), AV_OPT_TYPE_ ## type,          \
+      { .deffield = def }, min, max, FLAGS, __VA_ARGS__ }
+
+#define OPT_INT(name, field, def, min, max, descr, ...) \
+    OPT_GENERIC(name, field, def, min, max, descr, INT, i64, __VA_ARGS__)
+
+#define OPT_DBL(name, field, def, min, max, descr, ...) \
+    OPT_GENERIC(name, field, def, min, max, descr, DOUBLE, dbl, __VA_ARGS__)
+
+#define OPT_DUR(name, field, def, min, max, descr, ...) \
+    OPT_GENERIC(name, field, def, min, max, descr, DURATION, str, __VA_ARGS__)
+
+#define OPT_STR(name, field, def, min, max, descr, ...) \
+    OPT_GENERIC(name, field, def, min, max, descr, STRING, str, __VA_ARGS__)
+
+static const AVOption atone_options[] = {
+    OPT_INT("velocity",          velocity,       127,                                         0, 127,                 "set the velocity of key press",),
+    OPT_INT("v",                 velocity,       127,                                         0, 127,                 "set the velocity of key press",),
+    OPT_INT("sample_rate",       sample_rate,    44100,                                       1, INT_MAX,             "set the sample rate",),
+    OPT_INT("r",                 sample_rate,    44100,                                       1, INT_MAX,             "set the sample rate",),
+    OPT_DUR("duration",          duration,       0,                                           0, INT64_MAX,           "set the audio duration",),
+    OPT_DUR("d",                 duration,       0,                                           0, INT64_MAX,           "set the audio duration",),
+    OPT_STR("sfont",             sfont,          "/usr/share/sounds/sf2/FluidR3_GM.sf2",      0, 0,                   "set the soundfont file",),
+    OPT_INT("samples_per_frame", nb_samples,     1024,                                        0, INT_MAX,             "set the number of samples per frame",),
+    OPT_INT("MIDI_channel",      midi_chan,      0,                                           0, 16,                  "set the MIDI Channel",),
+    OPT_DBL("tone_change_interval",changerate,   0.2,                                         0, DBL_MAX,             "set the time to get next generation cells in seconds",),
+    OPT_DBL("t",                 changerate,     0.2,                                         0, DBL_MAX,             "set the time to get next generation cells in seconds",),
+    OPT_INT("rule",               rule,          30,                                          0, 255,                 "set the rule for changing value in cell",),
+    OPT_INT("width",             width,          64,                                          0, INT_MAX,             "set the width of the cell array",),
+    OPT_INT("tempo",             tempo,          120,                                         0, INT_MAX,             "set the beats per minute",),
+    {NULL}
+};
+
+AVFILTER_DEFINE_CLASS(atone);
+
+static void sequencer_callback(unsigned int time, fluid_event_t *event, fluid_sequencer_t *seq, void* data);
+
+static av_cold int init(AVFilterContext *ctx)
+{
+    AtoneContext *s = ctx->priv;
+    int n = s->rule;
+    /*Initialise the fluidsynth settings object followed by synthesizer*/
+    s->settings = new_fluid_settings();
+    if (s->settings == NULL){
+        av_log(s, AV_LOG_ERROR, "Failed to create the fluidsynth settings");
+        return AVERROR_EXTERNAL;
+    }
+    
+    s->synth = new_fluid_synth(s->settings);
+    if (s->synth == NULL){
+        av_log(s, AV_LOG_ERROR, "Failed to create the fluidsynth synth");
+        return AVERROR_EXTERNAL;
+    }
+
+    s->sfont_id = fluid_synth_sfload(s->synth, s->sfont, 1);
+    if(s->sfont_id == FLUID_FAILED){
+        av_log(s, AV_LOG_ERROR, "Loading the Soundfont Failed");
+        return AVERROR_EXTERNAL;
+    }
+    if (!(s->cells = av_malloc(sizeof(int)*(s->width))))
+        return AVERROR(ENOMEM);
+
+    if (!(s->nextgen = av_malloc(sizeof(int)*(s->width))))
+        return AVERROR(ENOMEM);
+    s->framecount=0;
+    s->sequencer = new_fluid_sequencer2(0);
+    /* register the synth with the sequencer */
+    s->synth_destination = fluid_sequencer_register_fluidsynth(s->sequencer, s->synth);
+    /* register the client name and callback */
+    s->client_destination = fluid_sequencer_register_client(s->sequencer, "atone", sequencer_callback, s);
+    s->time_marker = fluid_sequencer_get_tick(s->sequencer);
+    /*get change interval in frames/sec*/
+    s->changerate= s->changerate*s->sample_rate/s->nb_samples;
+    if (s->changerate<1.0)
+        s->changerate = 1.0;
+    /*get the beat duration in TICKS*/
+    s->beat_dur = 60000/s->tempo;
+    s->pattern_size = 5;
+    for (int i = 0; i < s->width; i++) 
+        s->cells[i] = 0;
+    s->cells[s->width/2] = 1;
+    for (int i = 0; i < s->pattern_size; i++)
+        s->notes[i] = 0; 
+    for (int i = 0; i<8; i++){
+        s->ruleset[i] = n%2;
+        n = n>>1;
+    }
+    return 0;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+    AtoneContext *s = ctx->priv;
+
+    delete_fluid_sequencer(s->sequencer);
+    delete_fluid_synth(s->synth);
+    delete_fluid_settings(s->settings);
+    av_freep(&s->cells);
+    av_freep(&s->nextgen);
+}
+
+static av_cold int config_props(AVFilterLink *outlink)
+{
+    AtoneContext *s = outlink->src->priv;
+
+    if (s->duration == 0)
+        s->infinite = 1;
+    s->duration = av_rescale(s->duration, s->sample_rate, AV_TIME_BASE);
+    if (s->framecount == INT_MAX)
+        s->framecount = 0;
+    return 0;
+}
+
+/* schedule a note on message */
+static void schedule_noteon(int chan, short key, unsigned int ticks, AtoneContext* s)
+{
+    fluid_event_t *ev = new_fluid_event();
+    fluid_event_set_source(ev, -1);
+    fluid_event_set_dest(ev,s->synth_destination);
+    fluid_event_noteon(ev, chan, key, s->velocity);
+    fluid_sequencer_send_at(s->sequencer, ev, ticks, 1);
+    delete_fluid_event(ev);
+}
+/* schedule a note off message */
+static void schedule_noteoff(int chan, short key, unsigned int ticks, AtoneContext* s)
+{
+    fluid_event_t *ev = new_fluid_event();
+    fluid_event_set_source(ev, -1);
+    fluid_event_set_dest(ev, s->synth_destination);
+    fluid_event_noteoff(ev, chan, key);
+    fluid_sequencer_send_at(s->sequencer, ev, ticks, 1);
+    delete_fluid_event(ev);
+}
+/* schedule a timer event to trigger the callback */
+static void schedule_timer_event(AtoneContext* s)
+{
+    fluid_event_t *ev = new_fluid_event();
+    fluid_event_set_source(ev, -1);
+    fluid_event_set_dest(ev, s->client_destination);
+    fluid_event_timer(ev, NULL);
+    fluid_sequencer_send_at(s->sequencer, ev, s->time_marker, 1);
+    delete_fluid_event(ev);
+}
+
+static void multiple_notes(int note_time, int start, int length, int* p_scale, int on, AtoneContext* s){
+    if (on == 1){
+        for (int i = start; i < length; i++)
+            if (s->notes[i] == 1)
+                schedule_noteon(s->midi_chan, p_scale[i], note_time, s);
+    }
+    else
+    {
+        for (int i = start; i < length; i++)
+            if (s->notes[i] == 1)
+                schedule_noteoff(s->midi_chan, p_scale[i], note_time, s);
+    }
+    
+}
+static void schedule_pattern(AtoneContext* s)
+{
+    enum on{OFF, ON};
+    int note_time, note_duration;
+    int p_scale[] = {60, 62, 65, 67, 69}; //major pentatonic scale
+    note_time = s->time_marker;
+    
+    if (s->notes[s->pattern_size/2] == 1){
+        note_duration = s->beat_dur;
+        multiple_notes(note_time, 0, s->pattern_size, p_scale, ON, s);
+        note_time += note_duration;
+        multiple_notes(note_time, 0, s->pattern_size, p_scale, OFF, s);
+    }
+    else{
+        note_duration = s->beat_dur/2;
+        multiple_notes(note_time, 0, s->pattern_size/2, p_scale, ON, s);
+        note_time += note_duration;
+        multiple_notes(note_time, s->pattern_size/2, s->pattern_size, p_scale, ON, s);
+        note_time += note_duration;
+        multiple_notes(note_time, 0, s->pattern_size, p_scale, OFF, s);
+    }
+    s->time_marker += s->beat_dur;
+}
+static void sequencer_callback(unsigned int time, fluid_event_t *event, fluid_sequencer_t *seq, void* data)
+{
+    
+    schedule_timer_event(data);
+    schedule_pattern(data);
+}
+
+/*
+Generate keys using cellular automata. Reference taken from http://tones.wolfram.com/about/how-it-works
+to generate the cells. Rule 30(default) gives random numbers. Here middle part(+-2) of the cell generation 
+is taken to get the keys. The keys generated are played in the major pentatonic scale, inspired by 
+https://twitter.com/teropa/status/880668931568132097.
+*/
+static void generate(AtoneContext* s){
+    for (int i=0; i< s->width; i++){
+        int c=0;
+        for (int j = 0; j < 3; j++){
+            c+= s->cells[(i+j-1)%s->width]<<(j);
+        }
+        s->nextgen[i] = s->ruleset[c];
+    }
+    memcpy(s->cells, s->nextgen, s->width*sizeof(int));
+    memcpy(s->notes, &s->cells[s->width/2-s->pattern_size/2], s->pattern_size*sizeof(int));
+}
+
+static int request_frame(AVFilterLink *outlink)
+{
+    AVFilterContext *ctx = outlink->src;
+    AtoneContext *s = ctx->priv;
+    AVFrame *frame;
+    int  nb_samples;
+    if (!s->infinite && s->duration <= 0) {
+        return AVERROR_EOF;
+    } else if (!s->infinite && s->duration < s->nb_samples) {
+        nb_samples = s->duration;
+    } else {
+        nb_samples = s->nb_samples;
+    }
+
+    if (!(frame = ff_get_audio_buffer(outlink, nb_samples)))
+        return AVERROR(ENOMEM);
+
+    if (s->framecount%((int)s->changerate) == 0){
+        generate(s);
+        schedule_pattern(s);
+        schedule_timer_event(s);
+    }
+    
+    fluid_synth_write_float(s->synth, nb_samples, frame->data[0], 0, 2, frame->data[0], 1, 2);
+    
+    if (!s->infinite)
+        s->duration -= nb_samples;
+
+    s->framecount++;
+    frame->pts = s->pts;
+    s->pts    += nb_samples;
+    return ff_filter_frame(outlink, frame);
+}
+
+static av_cold int query_formats(AVFilterContext *ctx)
+{
+    AtoneContext *s = ctx->priv;
+    static const int64_t chlayouts[] = { AV_CH_LAYOUT_STEREO, -1 };
+    int sample_rates[] = { s->sample_rate, -1 };
+    static const enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_NONE};
+    AVFilterFormats *formats;
+    AVFilterChannelLayouts *layouts;
+    int ret;
+
+    formats = ff_make_format_list(sample_fmts);
+    if (!formats)
+        return AVERROR(ENOMEM);
+    ret = ff_set_common_formats (ctx, formats);
+    if (ret < 0)
+        return ret;
+
+    layouts = avfilter_make_format64_list(chlayouts);
+    if (!layouts)
+        return AVERROR(ENOMEM);
+    ret = ff_set_common_channel_layouts(ctx, layouts);
+    if (ret < 0)
+        return ret;
+
+    formats = ff_make_format_list(sample_rates);
+    if (!formats)
+        return AVERROR(ENOMEM);
+    return ff_set_common_samplerates(ctx, formats);
+}
+
+
+static const AVFilterPad atone_outputs[] = {
+    {
+        .name          = "default",
+        .type          = AVMEDIA_TYPE_AUDIO,
+        .request_frame = request_frame,
+        .config_props  = config_props,
+    },
+    { NULL }
+};
+
+AVFilter ff_asrc_atone = {
+    .name          = "atone",
+    .description   = NULL_IF_CONFIG_SMALL("Generate tones using cellular automata."),
+    .query_formats = query_formats,
+    .init          = init,
+    .uninit        = uninit,
+    .priv_size     = sizeof(AtoneContext),
+    .inputs        = NULL,
+    .outputs       = atone_outputs,
+    .priv_class    = &atone_class,
+};
+
+
+
+
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 7b41018be7..4c4e8afe2d 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -30,7 +30,7 @@ 
 #include "libavutil/version.h"
 
 #define LIBAVFILTER_VERSION_MAJOR   7
-#define LIBAVFILTER_VERSION_MINOR  77
+#define LIBAVFILTER_VERSION_MINOR  78
 #define LIBAVFILTER_VERSION_MICRO 100