diff mbox series

[FFmpeg-devel,v4] libavfilter/asrc_atone.c : generate algorithmic music

Message ID 20200818112528.12131-1-ashutoshp012345@gmail.com
State New
Headers show
Series [FFmpeg-devel,v4] libavfilter/asrc_atone.c : generate algorithmic music | expand

Checks

Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Ashutosh Pradhan Aug. 18, 2020, 11:25 a.m. UTC
Generate algorithmic music using riffs, lindenmayer systems, cellular automaton and rhythm algorithms.
Fixed the error that was causing segmentation fault in the previous patch.

 Changelog                |    1 +
 configure                |    4 +
 doc/filters.texi         |  146 +++++
 libavfilter/Makefile     |    1 +
 libavfilter/allfilters.c |    1 +
 libavfilter/asrc_atone.c | 1343 ++++++++++++++++++++++++++++++++++++++++++++++
 libavfilter/notedef.h    |  269 ++++++++++
 libavfilter/version.h    |    2 +-
 8 files changed, 1766 insertions(+), 1 deletion(-)

Comments

Nicolas George Aug. 19, 2020, 12:41 p.m. UTC | #1
Ashutosh Pradhan (12020-08-18):
> Generate algorithmic music using riffs, lindenmayer systems, cellular automaton and rhythm algorithms.
> Fixed the error that was causing segmentation fault in the previous patch.

Thanks. (But this last sentence should be below the --- in the mail, not
in the commit message.)

I also notice that the output with the options given in example is much
more interesting than the default, and can justify the usefulness of the
filter. Good job!

Two points:

- Since it uses fluidsynth, the filter would probably better be called
  like that, especially since it does not produces tones but almost-real
  instrument sounds. Let us keep "atone" for a 100% internal
  implementation.

- I would really appreciate an answer to this question:

>> Since you know the API best, could you say in a few words how hard it
>> would be to get rid of fluidsynth and use an internal synthesizer
>> instead?

Regards,
Paul B Mahol Aug. 19, 2020, 2:23 p.m. UTC | #2
On 8/19/20, Nicolas George <george@nsup.org> wrote:
> Ashutosh Pradhan (12020-08-18):
>> Generate algorithmic music using riffs, lindenmayer systems, cellular
>> automaton and rhythm algorithms.
>> Fixed the error that was causing segmentation fault in the previous
>> patch.
>
> Thanks. (But this last sentence should be below the --- in the mail, not
> in the commit message.)
>
> I also notice that the output with the options given in example is much
> more interesting than the default, and can justify the usefulness of the
> filter. Good job!
>
> Two points:
>
> - Since it uses fluidsynth, the filter would probably better be called
>   like that, especially since it does not produces tones but almost-real
>   instrument sounds. Let us keep "atone" for a 100% internal
>   implementation.

Hmm, something about fluidsynthsounds?

>
> - I would really appreciate an answer to this question:
>
>>> Since you know the API best, could you say in a few words how hard it
>>> would be to get rid of fluidsynth and use an internal synthesizer
>>> instead?

Writing excellent synthesizer is not trivial task.

>
> Regards,
>
> --
>   Nicolas George
>
Nicolas George Aug. 19, 2020, 5:35 p.m. UTC | #3
Paul B Mahol (12020-08-19):
> Hmm, something about fluidsynthsounds?

That would be ok by me. Other suggestions: fluidsynthmusic, fluidmusic.

> Writing excellent synthesizer is not trivial task.

Indeed. But it is also of little use for this project.

On the other hand, writing a correct synthesizer that is also
trustworthy and bit-exact is achievable, and it would be very useful for
testing.

Therefore, I would really appreciate that Ashutosh Pradhan takes a few
instants to answer the question: how hard would it be to plug another
synthesizer?

I do not know what use you had in mind when proposing this project, but
the original proposal was never intended for listening, it was always
for testing, the audio equivalent of testsrc2.

Regards,
Paul B Mahol Aug. 19, 2020, 6:03 p.m. UTC | #4
On 8/19/20, Nicolas George <george@nsup.org> wrote:
> Paul B Mahol (12020-08-19):
>> Hmm, something about fluidsynthsounds?
>
> That would be ok by me. Other suggestions: fluidsynthmusic, fluidmusic.
>
>> Writing excellent synthesizer is not trivial task.
>
> Indeed. But it is also of little use for this project.
>
> On the other hand, writing a correct synthesizer that is also
> trustworthy and bit-exact is achievable, and it would be very useful for
> testing.
>
> Therefore, I would really appreciate that Ashutosh Pradhan takes a few
> instants to answer the question: how hard would it be to plug another
> synthesizer?
>
> I do not know what use you had in mind when proposing this project, but
> the original proposal was never intended for listening, it was always
> for testing, the audio equivalent of testsrc2.

Disagree, beside, you have already written correct, always bitexact synthesizer
that does not depend on external tools. So use that for testing?

>
> Regards,
>
> --
>   Nicolas George
>
Ashutosh Pradhan Aug. 20, 2020, 4:25 a.m. UTC | #5
On Wed, Aug 19, 2020 at 6:12 PM Nicolas George <george@nsup.org> wrote:

> Ashutosh Pradhan (12020-08-18):
> > Generate algorithmic music using riffs, lindenmayer systems, cellular
> automaton and rhythm algorithms.
> > Fixed the error that was causing segmentation fault in the previous
> patch.
>
> Thanks. (But this last sentence should be below the --- in the mail, not
> in the commit message.)
>
> I also notice that the output with the options given in example is much
> more interesting than the default, and can justify the usefulness of the
> filter. Good job!
>
> Two points:
>
> - Since it uses fluidsynth, the filter would probably better be called
>   like that, especially since it does not produces tones but almost-real
>   instrument sounds. Let us keep "atone" for a 100% internal
>   implementation.
>
> - I would really appreciate an answer to this question:
>
> >> Since you know the API best, could you say in a few words how hard it
> >> would be to get rid of fluidsynth and use an internal synthesizer
> >> instead?
>
I think it would be a bit difficult considering we have to read SoundFont
files, read and write midi events, code for the sequencer, synth, etc.

>
> Regards,
>
> --
>   Nicolas George
>
Nicolas George Aug. 20, 2020, 7:40 a.m. UTC | #6
Ashutosh Pradhan (12020-08-20):
> I think it would be a bit difficult considering we have to read SoundFont
> files, read and write midi events, code for the sequencer, synth, etc.

I mean precisely without doing all that. Your code produces notes at
certain times: can they be made available, their pitch and duration,
directly?

Regards,
Nicolas George Aug. 20, 2020, 7:47 a.m. UTC | #7
Paul B Mahol (12020-08-19):
> Disagree, beside, you have already written correct, always bitexact synthesizer
> that does not depend on external tools. So use that for testing?

You mean asrc_sine? It is not enough to exercise various code paths,
this is precisely the issue.
Ashutosh Pradhan Aug. 20, 2020, 2:02 p.m. UTC | #8
On Thu, Aug 20, 2020 at 1:10 PM Nicolas George <george@nsup.org> wrote:

> Ashutosh Pradhan (12020-08-20):
> > I think it would be a bit difficult considering we have to read SoundFont
> > files, read and write midi events, code for the sequencer, synth, etc.
>
> I mean precisely without doing all that. Your code produces notes at
> certain times: can they be made available, their pitch and duration,
> directly?
>
But, for that, we need to store the frequency information of each
instrument hence would be the same as reading SoundFont files, I think.
Also, the duration output would be the same as a note-on and note-off event.

> 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".
Nicolas George Aug. 20, 2020, 2:28 p.m. UTC | #9
Ashutosh Pradhan (12020-08-20):
> But, for that, we need to store the frequency information of each
> instrument hence would be the same as reading SoundFont files, I think.
> Also, the duration output would be the same as a note-on and note-off event.

Les me rephrase the question: how hard would it be to use another
synthesizer library with a slightly different API?

Regards,
Ashutosh Pradhan Aug. 20, 2020, 2:39 p.m. UTC | #10
On Thu, Aug 20, 2020 at 7:58 PM Nicolas George <george@nsup.org> wrote:

> Ashutosh Pradhan (12020-08-20):
> > But, for that, we need to store the frequency information of each
> > instrument hence would be the same as reading SoundFont files, I think.
> > Also, the duration output would be the same as a note-on and note-off
> event.
>
> Les me rephrase the question: how hard would it be to use another
> synthesizer library with a slightly different API?
> Not much I think.
> 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".
diff mbox series

Patch

diff --git a/Changelog b/Changelog
index 0108f8f1a8..0d759b7eb7 100644
--- a/Changelog
+++ b/Changelog
@@ -89,6 +89,7 @@  version 4.3:
 - PFM decoder
 - dblur video filter
 - Real War KVAG muxer
+- atone filter
 
 
 version 4.2:
diff --git a/configure b/configure
index 8de1afcb99..783bae8a03 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 atone source filter [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]
@@ -1774,6 +1775,7 @@  EXTERNAL_LIBRARY_LIST="
     libdc1394
     libdrm
     libflite
+    libfluidsynth
     libfontconfig
     libfreetype
     libfribidi
@@ -3493,6 +3495,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"
@@ -6336,6 +6339,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 d8cd45066a..f21b30ca47 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -6128,6 +6128,152 @@  anoisesrc=d=60:c=pink:r=44100:a=0.5
 @end example
 @end itemize
 
+@section atone
+
+Generate nice listenable algorithmic music.
+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 nb_samples
+Set the number of samples per each output frame. Default is 1024.
+
+@item sfont
+Specify the location of soundfont file. Default value is 
+"/usr/share/sounds/sf2/FluidR3_GM.sf2"(for ubuntu linux). Recommended to 
+use the FluidR3_GM general midi soundfont file.
+
+@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 between 0 to 127. Default value is 80.
+
+@item p_velocity
+Specify the velocity of key press for percussion track between 0 to 127. 
+Default value is 80.
+
+@item bpm
+Specify the beats per minute. Default is 80.
+
+@item seed
+Specify the seed for random number generator, must be an integer included between 0 and
+UINT32_MAX. If not specified, or if explicitly set to -1, the filter will use a random seed.
+
+@item algo
+Specify the algorithm type. Available options are riffs, lsystem, ca(cellular_automaton)
+and rhythm. Default is ca.
+
+@item instrument
+Specify the instrument for riffs and Lindenmayer system. Available instruments are Acoustic-Grand, 
+Bright-Acoustic, ... as defined in the General Midi specifications. Default is Acoustic-Grand.
+
+@item percussion
+Specify the percussion track for beats. Available options are Jazz1, 
+Jazz2, ..., Jazz6, Rock1...4, Shuffle, Metronome. Default is Metronome.
+
+@item numbars
+Set the number of bars in which riff energy will change between 0 to 8. Default is 2.
+
+@item scale
+Set the scale for Lindenmayer system and cellular automaton. Specify as root note_scale type.
+Specify scale types as major, n_minor for natural minor, m_minor for melodic minor, h_minor 
+as harmonic minor, p_major for pentatonic major, p_minor for pentatonic minor and blues for 
+blues scale. The root note is specified as C or Cs or Db for C or C sharp or D flat respectively.
+So scale specified as C_n_minor, Cs_p_major, etc. Default is C_major.
+
+@item height
+Set the height for mapping of scale for cellular automaton and Lindenmayer system. 
+It will map the upper and lower octaves. The range is from 10 to 25. Default value is 20.
+
+@item axiom
+Set the axiom for Lindenmayer system. Enter as combination of C, F, X, m, p, D. The symbols are 
+decoded as F-> increase note duration by factor of 2, X-> rest note, p-> move up in the scale 
+by one note, m-> move down in the scale by one note, C-> push current state, D-> set note 
+state to initial state. Default is "CFppFmmXD".
+
+@item rule1
+Set the rule 1 in the Lindenmayer system. Specify as "symbol"to"conversion". The rule is substituted 
+in the axiom till the specified number of generations. Default is "XtoFCppppFmmmmXDCmmFpppD".
+
+@item rule2
+Set the rule 2 in the Lindenmayer system. Default is "FtoCppppFmmmFpppFD".
+
+@item gen
+Set the number of generations to compute in the Lindenmayer system. In each generation, the symbol
+is converted as specified in rule1 and rule2. The 0th generation is axiom.
+
+@item ruletype
+Set the ruletype for cellular automaton. Recommended rule types are 7, 15, 31, 55, 61, 79, 91, 103, 
+110, 157, 167, 773, 1047, 1585. It is to decide the neighbor cells for computation. 7 gives neighbor
+cells as -1, 0, 1 and similar for other rules. Default is 31.
+
+@item rule
+Set the rule for cellular automaton. The range should be from 0 to 2^(2^number of neighbors) - 1.
+Default value is 367921.
+
+@item boundary
+Set the boundary type for cellular automaton. Allowed options are infinite and cyclic. 
+Default is cyclic.
+
+@item bass_instr
+Set the bass instrument for cellular automaton. Available instruments are Acoustic-Grand, 
+Bright-Acoustic, ... as defined in the General Midi specifications. Default is Acoustic-Grand.
+
+@item chord_instr
+Set the chords instrument for cellular automaton. Available instruments are Acoustic-Grand, 
+Bright-Acoustic, ... as defined in the General Midi specifications. Default is Acoustic-Grand.
+
+@item lead_instr
+Set the lead instrument for cellular automaton. Available instruments are Acoustic-Grand, 
+Bright-Acoustic, ... as defined in the General Midi specifications. Default is Acoustic-Grand.
+
+@item bass
+Set the bass algorithm for cellular automaton. Available options are lowest_notes and lower_eighth.
+Default is lowest_notes.
+
+@item chords
+Set the chords algorithm for cellular automaton. Available options are eighth, whole. Default is eighth
+
+@item lead
+Set the lead algorithm for cellular automaton. Available options are upper_eighth, upper_whole, 
+lower_eighth, lower_whole. Default is upper_eighth.
+
+@item r_algo
+Set the type of rhythm algorithm. Available options are padriddle, toggle, alternate, togpad for
+toggle and padriddle, altpad for alternate and padriddle, togalt for toggle and alternate. 
+Reference for the algorithms taken from 
+http://cgm.cs.mcgill.ca/~godfried/publications/Hawaii-Paper-Rhythm-Generation.pdf. Default is 
+altpad.
+
+@item maxres 
+Set the maximum resolution for the rhythm algorithm. Specify as 4 to have maximum resolution as
+quarter notes, 8 for eighth notes, 16 for sixteenth notes and so on for 32 and 64. Default is 16.
+
+@item density
+Set the expected density of notes in the rhythm algorithm as a percentage. Range is 1 to 100.
+Default is 75.
+
+@end table
+
+@subsection Examples
+
+@itemize
+
+@item
+Generate 10 seconds of riff music, with a key velocity of 100, instrument as Electric Guitar(jazz) 
+and percussion track as Jazz3:
+@example
+atone=algo=riffs:d=10:v=100:sfont="example.sf2":instrument=Electric-Guitar-Jazz:percussion=Jazz3
+atone=algo=riffs:duration=10:velocity=100:sfont="example.sf2":instrument=Electric-Guitar-Jazz:percussion=Jazz3
+@end example
+@end itemize
+
 @section hilbert
 
 Generate odd-tap Hilbert transform FIR coefficients.
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 0dc74f8b70..c4300a8594 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -148,6 +148,7 @@  OBJS-$(CONFIG_AEVALSRC_FILTER)               += aeval.o
 OBJS-$(CONFIG_AFIRSRC_FILTER)                += asrc_afirsrc.o
 OBJS-$(CONFIG_ANOISESRC_FILTER)              += asrc_anoisesrc.o
 OBJS-$(CONFIG_ANULLSRC_FILTER)               += asrc_anullsrc.o
+OBJS-$(CONFIG_ATONE_FILTER)                  += asrc_atone.o
 OBJS-$(CONFIG_FLITE_FILTER)                  += asrc_flite.o
 OBJS-$(CONFIG_HILBERT_FILTER)                += asrc_hilbert.o
 OBJS-$(CONFIG_SINC_FILTER)                   += asrc_sinc.o
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 3f70153986..a9d9c4b5a7 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -142,6 +142,7 @@  extern AVFilter ff_asrc_aevalsrc;
 extern AVFilter ff_asrc_afirsrc;
 extern AVFilter ff_asrc_anoisesrc;
 extern AVFilter ff_asrc_anullsrc;
+extern AVFilter ff_asrc_atone;
 extern AVFilter ff_asrc_flite;
 extern AVFilter ff_asrc_hilbert;
 extern AVFilter ff_asrc_sinc;
diff --git a/libavfilter/asrc_atone.c b/libavfilter/asrc_atone.c
new file mode 100644
index 0000000000..f5e7b556f8
--- /dev/null
+++ b/libavfilter/asrc_atone.c
@@ -0,0 +1,1343 @@ 
+/*
+ * 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 "libavutil/common.h"
+#include "audio.h"
+#include "avfilter.h"
+#include "internal.h"
+#include "notedef.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;
+    fluid_seq_id_t synth_destination;
+    fluid_seq_id_t client_destination;
+    unsigned int beat_dur;
+    unsigned int beats_pm;
+    unsigned int time_marker;
+    char *sfont;                      
+    int velocity;                    
+    int percussion_velocity;         
+    double changerate;              
+   
+    int *riffs;
+    int numriffs;
+    int last_note;
+    int framecount;
+    char *instrument;
+    int *track;
+    char *track_name;
+    int numbars;
+    int64_t seed;
+    AVLFG r;
+
+    char *axiom;
+    char *rule1;
+    char *rule2;
+    char *prevgen;
+    char *nextgen;
+    lsys *system;
+    int generations;
+    int lstate;
+    int max;
+
+    int ca_cells[32];
+    int ca_nextgen[32];
+    int *ca_neighbours;
+    int *ca_8keys[8];
+    int *ca_ruleset;
+    int *note_map;
+    int *scale;
+    int ca_boundary;
+    int ca_rule;
+    int ca_ruletype;
+    int height;
+    int ca_nsize;
+    void (*ca_generate)(int *curr, int *next, int *keys, int *nbor, int *ruleset, int size, int height, AVLFG *rand);
+    char *scale_name;
+    int last_bass_note;
+    int last_lead_note;
+    void (*schedule_pattern)(void *t);
+    int algorithm;
+    void (*ca_bass)(void *t);
+    void (*ca_chords)(void *t);
+    void (*ca_lead)(void *t);
+    int ca_bass_name;
+    int ca_chords_name;
+    int ca_lead_name;
+    char *chords_instr;
+    char *bass_instr;
+    char *lead_instr;
+
+    int *p_instr;
+    int *p_beats;
+    int p_maxres;
+    int p_density;
+    int p_barstate;
+    int p_algorithm;
+} AtoneContext;
+
+#define OFFSET(x) offsetof(AtoneContext, x)
+#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+
+enum boundary {
+    INFINITE, 
+    CYCLIC
+};
+
+enum bass_algorithm {
+    B_LOWEST_NOTES,
+    B_LOWER_EIGHTH
+};
+
+enum chord_algorithm {
+    C_EIGHTH,
+    C_WHOLE
+};
+
+enum lead_algortihm {
+    L_UPPER_EIGHTH,
+    L_UPPER_WHOLE,
+    L_LOWER_EIGHTH,
+    L_LOWER_WHOLE
+};
+
+enum rhythm_algorithm {
+    PADRIDDLE,
+    TOGGLE,
+    ALTERNATE,
+    TOGPAD,
+    ALTPAD,
+    TOGALT
+};
+
+enum algorithm {
+    RIFFS,
+    LSYSTEM,
+    CA,
+    RHYTHM
+};
+
+enum algo_channel{
+    RIFFNL, 
+    CA_BASS,
+    CA_LEAD, 
+    CA_CHORDS,
+    PERCUSSION = 9
+};
+
+static const AVOption atone_options[] = {
+    {"velocity",         "set velocity of key press",                    OFFSET(velocity),            AV_OPT_TYPE_INT,     {.i64 = 80},    0, 127,       FLAGS},
+    {"v",                "set velocity of key press",                    OFFSET(velocity),            AV_OPT_TYPE_INT,     {.i64 = 80},    0, 127,       FLAGS},
+    {"p_velocity",       "set percussion velocity",                      OFFSET(percussion_velocity), AV_OPT_TYPE_INT,     {.i64 = 80},    0, 127,       FLAGS},
+    {"sample_rate",      "set sample rate",                              OFFSET(sample_rate),         AV_OPT_TYPE_INT,     {.i64 = 44100}, 1, INT_MAX,   FLAGS},
+    {"r",                "set sample rate",                              OFFSET(sample_rate),         AV_OPT_TYPE_INT,     {.i64 = 44100}, 1, INT_MAX,   FLAGS},
+    {"duration",         "set duration in seconds",                      OFFSET(duration),            AV_OPT_TYPE_DURATION,{.i64 = 0},     0, INT64_MAX, FLAGS},
+    {"d",                "set duration in seconds",                      OFFSET(duration),            AV_OPT_TYPE_DURATION,{.i64 = 0},     0, INT64_MAX, FLAGS},
+    {"nb_samples",       "set number of samples per frame",              OFFSET(nb_samples),          AV_OPT_TYPE_INT,     {.i64 = 1024},  0, INT_MAX,   FLAGS},
+    {"seed",             "set seed for random number generator",         OFFSET(seed),                AV_OPT_TYPE_INT,     {.i64 = -1},    -1,INT_MAX,   FLAGS},
+    {"bpm",              "set beats per minute",                         OFFSET(beats_pm),            AV_OPT_TYPE_INT,     {.i64 = 80},    1, INT_MAX,   FLAGS},
+    {"sfont",            "set the path to soundfont file",               OFFSET(sfont), AV_OPT_TYPE_STRING, {.str = "/usr/share/sounds/sf2/FluidR3_GM.sf2"}, 0, 0, FLAGS},
+    {"instrument",       "set instrument for riff and L system",         OFFSET(instrument),          AV_OPT_TYPE_STRING,  {.str = "Acoustic-Grand"}, 0, 0, FLAGS},
+    {"percussion",       "set percussion track",                         OFFSET(track_name),          AV_OPT_TYPE_STRING,  {.str = "Shuffle"},      0, 0, FLAGS},
+    {"numbars",          "set number of bars in riff",                   OFFSET(numbars),             AV_OPT_TYPE_INT,     {.i64 = 2},     2, 8, FLAGS},
+    {"axiom",            "set the L system axiom",                       OFFSET(axiom),               AV_OPT_TYPE_STRING,  {.str = "CFppFmmXD"}, 0, 0, FLAGS},
+    {"rule1",            "set rule1 of L system",                        OFFSET(rule1),               AV_OPT_TYPE_STRING,  {.str = "XtoFCppppFmmmmXDCmmFpppD"}, 0, 0, FLAGS},
+    {"rule2",            "set rule2 of L system",                        OFFSET(rule2),               AV_OPT_TYPE_STRING,  {.str = "FtoCppppFmmmFpppFD"}, 0, 0, FLAGS},
+    {"gen",              "set no of generations of L system",            OFFSET(generations),         AV_OPT_TYPE_INT,     {.i64 = 3},     0, INT_MAX,   FLAGS},
+    {"ruletype",         "set ruletype of cellular automaton",           OFFSET(ca_ruletype),         AV_OPT_TYPE_INT,     {.i64  =  31},  0, INT_MAX,   FLAGS},
+    {"rule",             "set rule of cellular automaton",               OFFSET(ca_rule),             AV_OPT_TYPE_INT,     {.i64 = 367921},0, INT_MAX,   FLAGS},
+    {"height",           "set height for mapping of scale ",             OFFSET(height),              AV_OPT_TYPE_INT,     {.i64 = 20}, 10,25, FLAGS},
+    {"bass_instr",       "set bass instrument of cellular automaton",    OFFSET(bass_instr),          AV_OPT_TYPE_STRING,  {.str = "Acoustic-Grand"}, 0, 0, FLAGS},
+    {"chord_instr",      "set chords instrument of cellular automaton",  OFFSET(chords_instr),        AV_OPT_TYPE_STRING,  {.str = "Acoustic-Grand"}, 0, 0, FLAGS},
+    {"lead_instr",       "set lead instrument of cellular automaton",    OFFSET(lead_instr),          AV_OPT_TYPE_STRING,  {.str = "Acoustic-Grand"}, 0, 0, FLAGS}, 
+    {"scale",            "set scale for cellular automaton and L system",OFFSET(scale_name),          AV_OPT_TYPE_STRING,  {.str = "C_major"}, 0, 0, FLAGS},
+    {"bass",             "set bass algorithm for cellular automaton",    OFFSET(ca_bass_name),        AV_OPT_TYPE_INT,     {.i64 = B_LOWEST_NOTES}, 0, 1, FLAGS, "bass"},
+    {"lowest_notes",      0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = B_LOWEST_NOTES}, 0, 0, FLAGS, "bass"},
+    {"lower_eighth",      0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = B_LOWER_EIGHTH}, 0, 0, FLAGS, "bass"},
+    {"chords",           "set chords algorithm for cellular automaton",  OFFSET(ca_chords_name),      AV_OPT_TYPE_INT,     {.i64 = C_WHOLE},        0, 1, FLAGS, "chords"},
+    {"eighth",            0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = C_EIGHTH},       0, 0, FLAGS, "chords"},
+    {"whole",             0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = C_WHOLE},        0, 0, FLAGS, "chords"},
+    {"lead",             "set lead algorithm for cellular automaton",    OFFSET(ca_lead_name),        AV_OPT_TYPE_INT,     {.i64 = L_UPPER_WHOLE},  0, 3, FLAGS, "lead"},
+    {"upper_eighth",      0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = L_UPPER_EIGHTH}, 0, 0, FLAGS, "lead"},
+    {"upper_whole",       0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = L_UPPER_WHOLE},  0, 0, FLAGS, "lead"},
+    {"lower_eighth",      0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = L_LOWER_EIGHTH}, 0, 0, FLAGS, "lead"},
+    {"lower_whole",       0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = L_LOWER_WHOLE},  0, 0, FLAGS, "lead"},
+    {"boundary",         "set boundary type for cellular automaton",     OFFSET(ca_boundary),         AV_OPT_TYPE_INT,     {.i64 = CYCLIC},         0, 1, FLAGS, "boundary"}, 
+    {"infinite",          0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64= INFINITE},        0, 0, FLAGS, "boundary"},
+    {"cyclic",            0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64= CYCLIC},          0, 0, FLAGS, "boundary"},
+    {"maxres",           "set maximum resolution of rhythm algo",        OFFSET(p_maxres),            AV_OPT_TYPE_INT,     {.i64 = 16},             4, 64, FLAGS, "maxres"},
+    {"density",          "set density of notes in rhythm algo",          OFFSET(p_density),           AV_OPT_TYPE_INT,     {.i64 = 75},             1, 100, FLAGS},
+    {"r_algo",           "set the type for rhythm algorithm",            OFFSET(p_algorithm),         AV_OPT_TYPE_INT,     {.i64 = ALTPAD},         0, TOGALT, FLAGS, "r_algo"},
+    {"padriddle",         0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = PADRIDDLE},      0, 0, FLAGS, "r_algo"},
+    {"toggle",            0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = TOGGLE},         0, 0, FLAGS, "r_algo"},
+    {"alternate",         0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = ALTERNATE},      0, 0, FLAGS, "r_algo"},
+    {"togpad",            0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = TOGPAD},         0, 0, FLAGS, "r_algo"}, 
+    {"altpad",            0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = ALTPAD},         0, 0, FLAGS, "r_algo"}, 
+    {"togalt",            0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = TOGALT},         0, 0, FLAGS, "r_algo"},
+    {"algo",             "set algorithm name",                           OFFSET(algorithm),           AV_OPT_TYPE_INT,     {.i64 = CA},             0, RHYTHM, FLAGS, "algo"},
+    {"riffs",             0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = RIFFS},          0, 0, FLAGS, "algo"},
+    {"lsystem",           0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = LSYSTEM},        0, 0, FLAGS, "algo"},
+    {"ca",                0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = CA},             0, 0, FLAGS, "algo"},
+    {"cellular_automaton",0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = CA},             0, 0, FLAGS, "algo"},
+    {"rhythm",            0,                                             0,                           AV_OPT_TYPE_CONST,   {.i64 = RHYTHM},          0, 0, FLAGS, "algo"},
+    {NULL}
+};
+
+AVFILTER_DEFINE_CLASS(atone);
+
+static void instrument_select(int prog_no, unsigned int ticks, int channel, 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_program_change(ev, channel, prog_no);
+    fluid_sequencer_send_at(s->sequencer, ev, ticks, 1);
+    delete_fluid_event(ev);
+}
+
+/* schedule a note on message */
+static void schedule_noteon(int chan, short key, unsigned int ticks, int velocity, 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, 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, s);
+    fluid_sequencer_send_at(s->sequencer, ev, s->time_marker, 1);
+    delete_fluid_event(ev);
+}
+
+/*---Riffology---*/
+/*Determine the closest riff to the previous riff within
+ three tries to make the transition between riffs smoother*/
+static int pick_riff(AtoneContext *s)
+{
+    int min, dn, riff, bestriff = 0;
+    unsigned rand = av_lfg_get(&s->r) / 2;
+    
+    min = 999;
+    for (int i = 2; i >= 0; i--) {
+        riff = rand % s->numriffs;
+        if (s->last_note == 0)
+            return(riff);
+        dn = abs(s->last_note - s->riffs[riff * NPR]);
+        if (dn == 0)
+            dn = 6;
+        if (dn < min) {
+            bestriff = riff;
+            min = dn;
+        }
+    }
+
+    return bestriff;
+}
+
+/*Determine the energy of the player which will 
+affect the number of rests and holding tones*/
+static int energy_calc(int i, int numbars)
+{
+    if (3 * i < numbars)
+        return (100 - (90 * i)/numbars);
+    else if (3 * i > 2 * numbars)
+        return (40 + (90 * i)/numbars);
+    return 70;
+}
+
+static void play_riff(int riff, int energy, int note_duration, int note_time, AtoneContext *s)
+{
+    int pnd = 0, next; 
+    short pn = 0 ;
+    /*Beat importance values chosen such that off beat values are more likely to be skipped than on beat*/
+    int biv[] = {28, 0, 7, 0, 14, 0, 7, 4};
+    unsigned rand; 
+
+    for (int i = 0; i < NPR; i++) {
+        rand = av_lfg_get(&s->r) / 2;
+        next = s->riffs[riff * NPR + i];
+        if (next != H && next != R && ((energy + biv[i]) < rand % 100))
+            next = (rand < RAND_MAX / 2) ? H : R;
+        if (next == H) {
+            pnd ++;
+            continue;
+        }
+        
+        if (pn != R) {
+            schedule_noteon(RIFFNL, pn, note_time, s->velocity, s);
+            note_time += pnd*note_duration;
+            schedule_noteoff(RIFFNL, pn, note_time, s);
+            s->last_note = pn;
+        }
+        pn = next;
+        pnd = 1;
+    }
+
+    if (pn != R && pn != H) {
+        schedule_noteon(RIFFNL, pn, note_time, s->velocity, s);
+        note_time += pnd * note_duration;
+        schedule_noteoff(RIFFNL, pn, note_time, s);
+        s->last_note = pn;
+    }
+           
+}
+
+static void play_percussion(AtoneContext *s)
+{
+    int note_time = s->time_marker;
+
+    for (int i = 0; i < s->track[3]; i++)
+    {
+        /*percussion instruments in channel 10 */ 
+        schedule_noteon(PERCUSSION, s->track[4 * i], note_time, s->percussion_velocity, s);
+        schedule_noteon(PERCUSSION, s->track[4 * i + 1], note_time, s->percussion_velocity,s);
+        schedule_noteon(PERCUSSION, s->track[4 * i + 2], note_time, s->percussion_velocity,s);
+        /*Multiply by 4 as quarter note takes 1 beat, Whole note takes 4 beats and so on*/
+        note_time += 4 * s->beat_dur / s->track[3];
+        schedule_noteoff(PERCUSSION, s->track[4 * i], note_time, s);
+        schedule_noteoff(PERCUSSION, s->track[4 * i + 1], note_time, s);
+        schedule_noteoff(PERCUSSION, s->track[4 * i + 2], note_time, s);
+    }
+}
+
+/*Determine the pattern, tempo (to play as 8th, 16th or 32nd notes) and add the riffs to sequencer
+Reference: http://peterlangston.com/Papers/amc.pdf */
+static void schedule_riff_pattern(void *t)
+{
+    AtoneContext *s = t;
+    int note_time, note_duration, tempo, rpb, energy, riff;
+    unsigned rand = av_lfg_get(&s->r) / 2;
+
+    note_time = s->time_marker;
+    tempo = 1;
+    
+    if (tempo > rand % 3)
+        tempo--;
+    else if (tempo < rand % 3)
+        tempo++;
+    tempo = tempo % 3;
+    rpb = 1 << tempo;
+    note_duration = 4 * s->beat_dur / (NPR * rpb);
+    energy = energy_calc(rand % s->numbars, s->numbars);
+    for  (int r = 0; r < rpb; r++) {
+        riff = pick_riff(s);
+        play_riff(riff, energy, note_duration, note_time, s);
+        
+    }  
+    
+    play_percussion(s);
+    s->time_marker += 4 * s->beat_dur;   
+}
+
+/*---Lindenmayer System---*/
+/*Schedule 0L system pattern: decode symbols as : 
+F -> increase note duration by factor of 2
+X -> rest note
+p -> move up in scale by one note
+m -> move down in scale by one note
+{ -> push current state
+} -> set note state to initial value
+Reference : https://link.springer.com/chapter/10.1007%2F978-3-540-32003-6_56
+*/
+static void schedule_0L_pattern(AtoneContext *s)
+{
+    int note_state = s->height / 2, dur_state = 1, sys_state = 0, size = s->height;
+    char c;
+    
+    for (int i = 0; i < s->generations; i++) {
+        int j = 0, length = 0;
+        char c;
+
+        while (s->prevgen[j] != '\0') {
+            c = s->prevgen[j];
+            
+            if (length > L_MAX_LENGTH)
+                break;
+                
+            if (c == s->rule1[0]) {
+                memcpy(s->nextgen + length, s->rule1 + 3, strlen(s->rule1) - 3);
+                length += strlen(s->rule1) - 3;
+            }
+                
+            else if (c == s->rule2[0]) {
+                memcpy(s->nextgen + length, s->rule2 + 3, strlen(s->rule2) - 3);
+                length += strlen(s->rule2) - 3;
+            }
+                
+            else {
+                memcpy(s->nextgen+length, s->prevgen+j, 1);
+                length +=1;
+            }
+            j++;
+        }
+        s->nextgen[strlen(s->nextgen)] = '\0';
+        memcpy(s->prevgen, s->nextgen, strlen(s->nextgen) + 1);
+        strcpy(s->nextgen, "");
+    }
+
+    for (int i = 0 ; i < strlen(s->prevgen) ; i++) {
+        c = s->prevgen[i]; 
+        switch(c) {
+            case 'F': dur_state *= 2 ;break;
+            case 'p': note_state++; if (note_state >= size) note_state -= size/2; break;
+            case 'm': note_state--; if (note_state < 0) note_state += size/2;break;
+            case 'C': s->system[sys_state].note = s->note_map[note_state]; 
+                      s->system[sys_state].dur = dur_state; sys_state++; break;
+            case 'D': note_state = 0; dur_state = 1; break;
+            case 'X': s->system[sys_state].note = R; s->system[sys_state].dur = dur_state; 
+                      sys_state++; break;
+        }
+    }
+    
+    s->max = sys_state;
+}
+
+static void schedule_L_pattern(void *t)
+{
+    AtoneContext *s = t;
+    int note_time = s->time_marker, sum, state;
+    
+    sum = 0;
+    state = s->lstate; 
+    while (sum < 8) {
+        sum += s->system[state].dur;
+        state++;
+    }
+    
+    if (state < s->max)
+        for (int i = s->lstate; i < state ; i++) {
+            if (s->system[i].note == R) {
+                note_time += 4 * s->beat_dur * s->system[i].dur / 8;
+            }
+            else {
+                schedule_noteon(RIFFNL, s->system[i].note, note_time, s->velocity, s);
+                note_time += 4 * s->beat_dur*s->system[i].dur / 8;
+                schedule_noteoff(RIFFNL, s->system[i].note, note_time, s);
+            }
+            
+        }
+    
+    s->lstate += state;
+    play_percussion(s);
+    s->time_marker += 4*s->beat_dur;
+}
+
+/*---Cellular Automaton---*/
+static void multiple_notes(int note_time, int start, int length, int on, int *notes, AtoneContext *s)
+{
+    if (on == 1){
+        for (int i = start; i < length; i ++)
+                schedule_noteon(CA_CHORDS, notes[i], note_time, 2 * s->velocity / 3, s);
+    }
+    else {
+        for (int i = start; i < length; i ++)
+                schedule_noteoff(CA_CHORDS, notes[i], note_time, s);
+    }
+    
+}
+
+static void cyclic_generate (int *curr, int *next, int *keys, int *nbor, int *ruleset, int size, int height, AVLFG *rand)
+{
+    for (int i = 0; i < 32; i++) {
+        int c = 0;
+
+        for (int j = 0; j < size; j++) {
+            c +=  curr[(i + nbor[j]+ 32) % 32] << j;
+        }
+        next[i] = ruleset[c];
+    }
+    
+    memcpy(curr, next, 32 * sizeof(int));
+    memcpy(keys, &curr[16 - height / 2], height * sizeof(int));
+}
+
+/*Keep the ratio of 0 and 1 in cell array of cellular automaton same as in rule to simulate infinite boudary */
+static void infinite_generate (int *curr, int *next, int *keys, int *nbor, int *ruleset, int size, int height, AVLFG *rand)
+{
+    float rp = 0.0;
+
+    for (int i = 0; i < (1 << size); i++)
+        rp += ruleset[i] * 1.0 / (1 << size);
+    for (int i = 0; i < 32; i++){
+        int c = 0;
+
+        for (int j = 0; j < size; j++){
+            if ((i + nbor[j]) >= size || (i + nbor[j]) < 0){
+                float x = av_lfg_get(rand) * 0.5 / INT_MAX;
+
+                if (x > rp){
+                    c += 1 << j;
+                }
+            }
+            else
+                c +=  curr[i + nbor[j]] << j;
+        }
+        
+        next[i] = ruleset[c];
+    }
+    memcpy(curr, next, 32 * sizeof(int));
+    memcpy(keys, &curr[16 - height / 2], height * sizeof(int));
+}
+
+static void ca_bass_lowest_notes (void *t) 
+{
+    AtoneContext *s = t;
+    int note_time = s->time_marker;
+
+    for (int j = 0; j < 8; j++) {
+        int i = 0;
+
+        while (i < s->height / 3) {
+            if (s->ca_8keys[j][i] == 1) {
+                s->last_bass_note = i;
+                break;
+            }
+            i++;
+        }
+        schedule_noteon (CA_BASS, s->note_map[s->last_bass_note % s->height], note_time, 3 * s->velocity / 4, s);
+        note_time += 4 * s->beat_dur / 8;
+        schedule_noteoff(CA_BASS, s->note_map[s->last_note%s->height], note_time, s);
+    }
+}
+
+/*Each note obtained is played as a 1/8 note
+Random number obtained is % (2 * i + 1) to increase bias towards upper notes*/
+static void ca_bass_lower_eighth (void *t) 
+{
+    AtoneContext *s = t;
+    int note_time = s->time_marker, note = s->last_bass_note;
+
+    for (int j = 0; j < 8; j++) {
+        unsigned max = 0;
+
+        for (int i = FFMAX(0, s->last_bass_note - 3); i < FFMIN(s->last_bass_note + 3, s->height / 2); i++) {
+            unsigned rand = (av_lfg_get(&s->r) * s->ca_8keys[j][i]) % (2 * i + 1);
+
+            if (max < rand) {
+                max = rand;
+                note = i;
+            }
+        }
+        if (max > 0) {
+            s->last_bass_note = note;
+            schedule_noteon (CA_BASS, s->note_map[s->last_bass_note % s->height], note_time, 2 * s->velocity / 3, s);
+            note_time += 4 * s->beat_dur / 8;
+            schedule_noteoff(CA_BASS, s->note_map[s->last_note%s->height], note_time, s);
+        }
+    }
+}
+
+static void ca_chords_eighth (void *t) 
+{
+    enum {ON, OFF};
+    AtoneContext *s = t;
+    int note_time = s->time_marker, note = s->last_note, notes[3];
+    
+    for (int j = 0; j < 8; j++) {
+        unsigned max = 0;
+
+        for (int i = 0; i < s->height; i++) {
+            unsigned rand = (av_lfg_get(&s->r) * s->ca_8keys[j][i]) % (2 * i + 1);
+
+            if ((s->ca_8keys[j][i] % s->height) == 1 && (s->ca_8keys[j][i + 2] % s->height) == 1 && (s->ca_8keys[j][i + 4] % s->height) == 1) {
+                if (max < rand) {
+                    max = rand;
+                    note  = i;
+                }
+            }
+        }
+        if (max > 0) {
+            s->last_note = note;
+            for (int i = 0; i < 3; i++)
+                notes[i] = s->note_map[(s->last_note + 2 * i) % s->height];
+            multiple_notes (note_time, 0, 3, ON, notes, s);
+            note_time += 4 * s->beat_dur / 8;
+            multiple_notes (note_time, 0, 3, OFF, notes, s);
+        }
+    }
+}
+
+static void ca_chords_whole (void *t) 
+{
+    enum {ON, OFF};
+    AtoneContext *s = t;
+    int note_time = s->time_marker, note[8], notes[3], k;
+    
+    for (int j = 0; j < 8; j++) {
+        unsigned max = 0;
+
+        note[j] = 0;
+        for (int i = 0; i < s->height; i++) {
+            unsigned rand = (av_lfg_get(&s->r) * s->ca_8keys[j][i]) % (2 * i + 1);
+
+            if ((s->ca_8keys[j][i] % s->height) == 1 && (s->ca_8keys[j][i + 2] % s->height) == 1 && (s->ca_8keys[j][i + 4] % s->height) == 1) {
+                if (max < rand) {
+                    max = rand;
+                    k  = i;
+                }
+            }
+        }
+        if (max > 0)
+            note[j] = k;
+    }
+    k = 0;
+    while (k < 8) {
+        int j = 0;
+        if (note[k] > 0) {
+            s->last_note = note[k];
+            for (int i = 0; i < 3; i++)
+                notes[i] = s->note_map[(s->last_note + 2 * i) % s->height];
+            multiple_notes (note_time, 0, 3, ON, notes, s);
+            note_time += 4 * s->beat_dur / 8;
+            while ( k + j < 8) {
+                if (note[k+j] > 0 && note[k + j] == note[k]) {
+                    note_time += 4 * s->beat_dur/8;
+                    j++;
+                }
+                else 
+                    break;      
+            }
+            multiple_notes (note_time, 0, 3, OFF, notes, s);
+        }
+        k += j + 1;
+    }
+}
+
+static void ca_lead_upper_whole (void *t) 
+{
+    AtoneContext *s = t;
+    int note_time = s->time_marker, note[8], k;
+  
+    for (int j = 0; j < 8; j++) {
+        unsigned max = 0; 
+
+        note[j] = 0;
+        for (int i = FFMAX(s->last_lead_note - 3, s->height/3); i < FFMIN(s->last_lead_note + 3, s->height); i++) {
+            unsigned rand = (av_lfg_get(&s->r) * s->ca_8keys[j][i]) % (5 * i + 1);
+
+            if (max < rand) {
+                max = rand;
+                k = i;
+            }
+        }
+        if (max > 0)
+            note[j] = k;
+    }
+    k = 0;
+    while(k < 8){
+        int j = 0;
+        if (note[k] > 0) {
+            s->last_lead_note = note[k];
+            schedule_noteon (CA_LEAD, s->note_map[s->last_lead_note % s->height], note_time, s->velocity, s);
+            note_time += 4 * s->beat_dur / 8;
+            while ( k + j < 8) {
+                if (note[k+j] > 0 && note[k + j] == note[k]) {
+                    note_time += 4 * s->beat_dur / 8;
+                    j++;
+                }
+                else 
+                    break;      
+            }  
+            schedule_noteoff(CA_LEAD, s->note_map[s->last_lead_note % s->height], note_time, s);
+        }
+        k += j+1;
+    }  
+}
+
+static void ca_lead_lower_whole (void *t) 
+{
+    AtoneContext *s = t;
+    int note_time = s->time_marker, note[8], k;
+  
+    for (int j = 0; j < 8; j++) {
+        unsigned max = 0; 
+
+        note[j] = 0;
+        for (int i = FFMAX(s->last_lead_note - 3, s->height/3); i < FFMIN(s->last_lead_note + 3, s->height); i++) {
+            unsigned rand = (av_lfg_get(&s->r) * s->ca_8keys[j][i]) % (5 * FFABS(s->height - i) + 1);
+
+            if (max < rand) {
+                max = rand;
+                k = i;
+            }
+        }
+        if (max > 0)
+            note[j] = k;
+    }
+    k = 0;
+    while(k < 8){
+        int j = 0;
+        if (note[k] > 0) {
+            s->last_lead_note = note[k];
+            schedule_noteon (CA_LEAD, s->note_map[s->last_lead_note % s->height], note_time, s->velocity, s);
+            note_time += 4 * s->beat_dur / 8;
+            while ( k + j < 8) {
+                if (note[k+j] > 0 && note[k + j] == note[k]) {
+                    note_time += 4 * s->beat_dur / 8;
+                    j++;
+                }
+                else 
+                    break;      
+            }  
+            schedule_noteoff(CA_LEAD, s->note_map[s->last_lead_note % s->height], note_time, s);
+        }
+        k += j + 1;
+    }  
+}
+
+static void ca_lead_upper_eighth (void *t) 
+{
+    AtoneContext *s = t;
+    int note_time = s->time_marker, note = s->last_lead_note;
+    
+    for (int j = 0; j < 8; j++) {
+        unsigned max = 0;
+        
+        for (int i = FFMAX(s->last_lead_note - 3, s->height/3); i < FFMIN(s->last_lead_note + 3, s->height); i++) {
+            unsigned rand = (av_lfg_get(&s->r) * s->ca_8keys[j][i]) % (5 * i + 1);
+
+            if (max < rand) {
+                max = rand;
+                note = i;
+            }
+        }
+        if (max > 0) {
+            s->last_lead_note = note;
+            schedule_noteon (CA_LEAD, s->note_map[s->last_lead_note % s->height], note_time, s->velocity, s);
+            note_time += 4 * s->beat_dur / 8;
+            schedule_noteoff(CA_LEAD, s->note_map[s->last_lead_note % s->height], note_time, s);
+        }
+    }
+}
+
+static void ca_lead_lower_eighth (void *t) 
+{
+    AtoneContext *s = t;
+    int note_time = s->time_marker, note = s->last_lead_note;
+    
+    
+    for (int j = 0; j < 8; j++) {
+        unsigned max = 0;
+
+        for (int i = FFMAX(s->last_lead_note - 3, s->height / 3); i < FFMIN(s->last_lead_note + 3, s->height); i++) {
+            unsigned rand = (av_lfg_get(&s->r) * s->ca_8keys[j][i]) % (5 * FFABS(s->height - i) + 1);
+
+            if (max < rand) {
+                max = rand;
+                note = i;
+            }
+        }
+        if (max > 0) {
+            s->last_lead_note = note;
+            schedule_noteon (CA_LEAD, s->note_map[s->last_lead_note % s->height], note_time, s->velocity, s);
+            note_time += 4 * s->beat_dur / 8;
+            schedule_noteoff(CA_LEAD, s->note_map[s->last_lead_note%s->height], note_time, s);
+        }
+    }
+    
+}
+
+static void schedule_ca_pattern(void *t)
+{
+    AtoneContext *s = t;
+    
+    for (int i = 0; i < 8; i++)
+        s->ca_generate(s->ca_cells, s->ca_nextgen, s->ca_8keys[i], s->ca_neighbours, s->ca_ruleset, s->ca_nsize, s->height, &s->r);
+    s->ca_bass(s);
+    s->ca_chords(s);
+    s->ca_lead(s);
+    play_percussion(s);
+    s->time_marker += 4 * s->beat_dur;
+    
+}
+
+/*---Rhythm---*/
+/*Stochastically subdivide and set value to 1*/
+static void divvy(int lo, int hi, AtoneContext *s) 
+{
+    int mid;
+    unsigned rand = av_lfg_get(&s->r);
+
+    mid = (lo + hi) >> 1;
+    s->p_instr[lo] = 1;
+    if (rand % 101 < s->p_density && hi - lo > 1) {
+        divvy(lo, mid, s);
+        divvy(mid, hi, s);
+    }
+}
+
+static int get_p_instr(AtoneContext *s) 
+{
+    int instr = av_lfg_get(&s->r) % 4;
+
+    switch (instr) {
+    case 0: instr = drums[av_lfg_get(&s->r) % FF_ARRAY_ELEMS(drums)];break;
+    case 1: instr = toms[av_lfg_get(&s->r) % FF_ARRAY_ELEMS(toms)];break;
+    case 2: instr = cymbals[av_lfg_get(&s->r) % FF_ARRAY_ELEMS(cymbals)];break;
+    case 3: instr = hi_hats[av_lfg_get(&s->r) % FF_ARRAY_ELEMS(hi_hats)];break;
+    }
+    return instr;
+}
+
+/*Reference taken from : 
+http://cgm.cs.mcgill.ca/~godfried/publications/Hawaii-Paper-Rhythm-Generation.pdf
+Reflect the first half of the pattern in second half*/
+static void padriddle(AtoneContext *s)
+{
+    divvy(0, s->p_maxres, s);
+    for (int i = 0; i < s->p_maxres / 2; i++) {
+        s->p_instr[i] = get_p_instr(s) * s->p_instr[i];
+        s->p_instr[s->p_maxres / 2 + i] = s->p_instr[i];
+        s->p_beats[i] = s->p_maxres;
+        s->p_beats[s->p_maxres / 2 + i] = s->p_maxres;
+    }
+}
+
+/*This will give beats of the type [xxx.] or [xxxxxxx.]*/
+static void alternate(AtoneContext *s)
+{
+    int i, rep_size, newsize, rep_array[] = {4, 8, 16, 32};
+    
+    for (i = 0; i < 4; i++) {
+        if (s->p_maxres < rep_array[i])
+            break;
+    }
+    
+    rep_size = rep_array[av_lfg_get(&s->r) % i];
+    newsize = s->p_maxres - s->p_maxres / rep_size;
+    divvy(0, newsize, s);
+    for (int i = 0; i < newsize; i++) {
+        s->p_instr[i] = s->p_instr[i] * get_p_instr(s);
+        if ((i + 1) % (rep_size - 1) == 0)
+            s->p_beats[i] = s->p_maxres / 2;
+        else
+            s->p_beats[i] = s->p_maxres;
+    }
+    
+    s->p_maxres = newsize;
+}
+
+/*Toggle between the instruments in the first half and second half*/
+static void toggle(AtoneContext *s)
+{
+    int instr1 = get_p_instr(s), instr2 = get_p_instr(s);
+    divvy(0, s->p_maxres/2, s);
+    for (int i = 0; i < s->p_maxres / 2; i++) {
+        s->p_instr[i] = instr1 * s->p_instr[i];
+        s->p_instr[s->p_maxres / 2 + i] = instr2 * s->p_instr[i] / instr1;
+        s->p_beats[i] = s->p_maxres;
+        s->p_beats[s->p_maxres / 2 + i] = s->p_maxres; 
+    }
+}
+
+static void alternate_n_padriddle(AtoneContext *s) 
+{
+    alternate(s);
+    for (int i = 0; i < s->p_maxres / 2; i++) {
+        s->p_instr[s->p_maxres / 2 + i] = s->p_instr[i];
+    }
+}
+
+static void toggle_n_padriddle(AtoneContext *s) 
+{
+    s->p_maxres = s->p_maxres / 2;
+    toggle(s);
+    s->p_maxres = s->p_maxres * 2;
+    for (int i = 0; i < s->p_maxres / 2; i++) {
+        s->p_instr[s->p_maxres / 2 + i] = s->p_instr[i];
+        s->p_beats[s->p_maxres / 2 + i] = s->p_beats[i];
+    }
+}
+
+static void alternate_n_toggle(AtoneContext *s)
+{
+    int instr1 = get_p_instr(s), instr2 = get_p_instr(s);
+
+    alternate(s);
+    for (int i = 0; i < s->p_maxres / 2; i++) {
+        s->p_instr[i] = instr1 * FFMIN(1, s->p_instr[i]);
+        s->p_instr[s->p_maxres / 2 + i] = instr2 * FFMIN(1, s->p_instr[s->p_maxres / 2 + i]);
+    }
+}
+
+static void schedule_r_pattern(void *t)
+{
+    AtoneContext *s = t;
+    int note_time = s->time_marker;
+
+    for (int i = 0; i < s->p_maxres; i++) {
+        schedule_noteon(PERCUSSION, s->p_instr[i], note_time, s->percussion_velocity, s);
+        note_time += 4 * s->beat_dur / s->p_beats[i];
+        schedule_noteoff(PERCUSSION, s->p_instr[i], note_time, s);
+    }
+    
+    s->time_marker += 4 * s->beat_dur;
+}
+
+static void sequencer_callback(unsigned int time, fluid_event_t *event, fluid_sequencer_t *seq, void *data)
+{
+    AtoneContext *s = data;
+    
+    schedule_timer_event(data);
+    s->schedule_pattern(data);
+}
+
+static int get_scale (AtoneContext *s) 
+{
+    int s_size, x[7];
+
+    switch (s->scale_name[0]) {
+    case 'C': x[0] = C3; break;
+    case 'D': x[0] = D3; break;
+    case 'E': x[0] = E3; break;
+    case 'F': x[0] = F3; break;
+    case 'G': x[0] = G3; break;
+    case 'A': x[0] = A3; break;
+    case 'B': x[0] = B3; break;
+    default: x[0] = C3; break;
+    }
+
+    switch (s->scale_name[1]) {
+    case 'b': x[0] -= 1; break;
+    case 's': x[0] += 1; break;
+    }
+
+    if (strcmp(s->scale_name+2, "major") == 0 || strcmp(s->scale_name+3, "major") == 0) {
+        for (int i = 0; i < FF_ARRAY_ELEMS(major_increment); i++)
+           x[i + 1] = x[i] + major_increment[i];
+        s_size = 7;
+    }
+    else if (strcmp(s->scale_name+2, "n_minor") == 0 || strcmp(s->scale_name+3, "n_minor") == 0) {
+        for (int i = 0; i < FF_ARRAY_ELEMS(natural_minor_increment); i++)
+            x[i + 1] = x[i] + natural_minor_increment[i];
+        s_size = 7;
+    }
+    else if (strcmp(s->scale_name+2, "m_minor") == 0 || strcmp(s->scale_name+3, "m_minor") == 0) {
+        for (int i = 0; i < FF_ARRAY_ELEMS(melodic_minor_increment); i++)
+            x[i + 1] = x[i] + melodic_minor_increment[i];
+        s_size = 7;
+    }
+    else if (strcmp(s->scale_name+2, "h_minor") == 0 || strcmp(s->scale_name+3, "h_minor") == 0) {
+        for (int i = 0; i < FF_ARRAY_ELEMS(harmonic_minor_increment); i++)
+            x[i + 1] = x[i] + harmonic_minor_increment[i];
+        s_size = 7;
+    }
+    else if (strcmp(s->scale_name+2, "p_major") == 0 || strcmp(s->scale_name+3, "p_major") == 0) {
+        for (int i = 0; i < FF_ARRAY_ELEMS(major_pentatonic_increment); i++)
+            x[i + 1] = x[i] + major_pentatonic_increment[i];
+        s_size = 5;
+    }
+    else if (strcmp(s->scale_name+2, "p_minor") == 0 || strcmp(s->scale_name+3, "p_minor") == 0) {
+        for (int i = 0; i < FF_ARRAY_ELEMS(minor_pentatonic_increment); i++)
+            x[i + 1] = x[i] + minor_pentatonic_increment[i];
+        s_size = 5;
+    }
+    else if (strcmp(s->scale_name+2, "blues") == 0 || strcmp(s->scale_name+3, "blues") == 0) {
+        for (int i = 0; i < FF_ARRAY_ELEMS(blues_increment); i++)
+            x[i + 1] = x[i] + blues_increment[i];
+        s_size = 6;
+    }
+    else {
+        av_log(s, AV_LOG_WARNING, "scale %s not found! defaulting to a major scale\n", s->scale_name);
+        for (int i = 0; i < FF_ARRAY_ELEMS(major_increment); i++)
+            s->scale[i + 1] = s->scale[i] + major_increment[i];
+        s_size = 7;
+    } 
+
+    if (!(s->scale = av_malloc(s_size * sizeof(int))))
+        return AVERROR(ENOMEM);
+    memcpy(s->scale, x, s_size * sizeof(int));  
+
+    return s_size;
+}
+
+static int find_instrument(char *instrument, AtoneContext *s)
+{
+    for (int i = 0; i < FF_ARRAY_ELEMS(GM_instrument_list); i++)
+        if (strcmp(GM_instrument_list[i], instrument) == 0)
+            return i;   
+    
+    av_log(s, AV_LOG_WARNING, "instrument %s "
+               "not found! defaulting to Acoustic-Grand\n", instrument);
+    return 0;
+}
+
+static av_cold int init(AVFilterContext *ctx)
+{
+    AtoneContext *s = ctx->priv;
+    int sfont_id, copy, i = 1, j = 1, t = 0, s_size;
+
+    /*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;
+    }
+
+    sfont_id = fluid_synth_sfload(s->synth, s->sfont, 1);
+    if (sfont_id == FLUID_FAILED) {
+        av_log(s, AV_LOG_ERROR, "Loading the Soundfont Failed");
+        return AVERROR_EXTERNAL;
+    }
+    
+    if (!(s->riffs = av_malloc(sizeof(riff))))
+        return AVERROR(ENOMEM);
+    if (!(s->prevgen = av_malloc(sizeof(char) * L_MAX_LENGTH)))
+        return AVERROR(ENOMEM);
+    if (!(s->nextgen = av_malloc(sizeof(char) * L_MAX_LENGTH)))
+        return AVERROR(ENOMEM);
+    if (!(s->system = av_malloc(sizeof(lsys) * L_MAX_LENGTH)))
+        return AVERROR(ENOMEM);
+    strcpy(s->prevgen, s->axiom);
+
+    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 the beat duration in TICKS     1 quarter note per beat*/
+    s->beat_dur = 60000/s->beats_pm;
+    /*get change interval in frames/sec*/
+    s->changerate = (4 * s->beat_dur) * s->sample_rate / s->nb_samples;
+    if (s->changerate < 1.0)
+        s->changerate = 1.0;
+
+    s->lstate = 0;
+    s->max = 0;
+    s->last_note = 0;
+    s->last_bass_note = 0;
+    s->last_lead_note = s->height / 2;
+    s->numriffs = sizeof(riff)/(NPR * sizeof(int));
+    if (s->seed == -1)
+        s->seed = av_get_random_seed();
+    av_lfg_init(&s->r, s->seed);
+
+    for (int i = 0; i < s->numriffs * NPR ; i++)
+        s->riffs[i] = riff[i];
+
+    s->ca_nsize = 0;
+    copy = s->ca_ruletype;
+    while (copy > 0) {
+        if (copy % 2 == 1)
+            s->ca_nsize++;
+        copy = copy >> 1;
+    }
+    if (!(s->ca_neighbours = av_malloc(sizeof(int) * s->ca_nsize)))
+        return AVERROR(ENOMEM);
+    if (!(s->ca_ruleset = av_malloc(sizeof(int) * (1 << s->ca_nsize))))
+        return AVERROR(ENOMEM);
+    for (int k = 0; k < 8; k++)
+        if (!(s->ca_8keys[k] = av_malloc(s->height * sizeof(int))))
+            return AVERROR(ENOMEM);
+    if (!(s->note_map = av_malloc(sizeof(int) * s->height)))
+        return AVERROR(ENOMEM);
+    s_size = get_scale(s);
+    if (s_size == AVERROR(ENOMEM))
+        return AVERROR(ENOMEM);
+    copy = s->ca_ruletype;
+    
+    /*The neighbouring cells on which cells of next generation is determined as
+    in http://tones.wolfram.com/about/how-it-works*/
+    while (copy > 0) {
+        if (copy % 2 == 1){
+            if (i % 2 == 0)
+                s->ca_neighbours[(s->ca_nsize - 1) / 2 + j / 2] = -1 * (i/2);
+            else
+                s->ca_neighbours[(s->ca_nsize - 1) / 2 - j / 2] = (i/2);
+            j++;
+        }
+        copy = copy >> 1;
+        i++;
+    }
+    copy = s->ca_rule;
+    i = 0;
+    while (i != (1 << s->ca_nsize)) {
+        s->ca_ruleset[i++] = copy % 2;
+        copy = copy >> 1; 
+    }
+
+    /*In cellular automaton, the middle portion(s->height) is mapped to a scale 
+    The lower and upper octaves are mapped by subtracting and adding 12 respectively*/
+    j = s_size/2 - (s->height+1)/4;
+    for (i = 0; i < s->height; i++) {
+        if (j < 0)
+            s->note_map[i] = s->scale[s_size + j % s_size] - 12 * (int)((j * -1.0) / s_size + 1) ;
+        else
+            s->note_map[i] = s->scale[j % s_size] + 12 * (int)((j * 1.0) / s_size);
+        j++;    
+    }   
+
+    for (i = 0; i < 32; i++)
+        s->ca_cells[i] = av_lfg_get(&s->r) % 2;
+    
+    if (!(s->track = av_malloc(sizeof(int) * MAX_TRACK_SIZE)))
+        return AVERROR(ENOMEM);
+    
+    for (t = 0 ; t < FF_ARRAY_ELEMS(percussion_tracks) ; t++)
+        if (strcmp(percussion_tracks[t], s->track_name) == 0)
+            break;
+        
+    switch (t) {
+    case 0: memcpy(s->track, Track1, sizeof(Track1)); break;
+    case 1: memcpy(s->track, Track2, sizeof(Track2)); break;
+    case 2: memcpy(s->track, Track3, sizeof(Track3)); break;
+    case 3: memcpy(s->track, Track4, sizeof(Track4)); break;
+    case 4: memcpy(s->track, Track5, sizeof(Track5)); break;
+    case 5: memcpy(s->track, Track6, sizeof(Track6)); break;
+    case 6: memcpy(s->track, Track7, sizeof(Track7)); break;
+    case 7: memcpy(s->track, Track8, sizeof(Track8)); break;
+    case 8: memcpy(s->track, Track9, sizeof(Track9)); break;
+    case 9: memcpy(s->track, Track10, sizeof(Track10)); break;
+    case 10: memcpy(s->track, Track11, sizeof(Track11)); break;
+    case 11: memcpy(s->track, Track12, sizeof(Track12)); break;
+    default: av_log(s, AV_LOG_WARNING, "percussion track %s "
+            "not found! defaulting to Metronome\n", s->track_name);
+            memcpy(s->track, Track12, sizeof(Track12)); break;
+    }
+    
+    switch (s->ca_boundary) {
+    case INFINITE: s->ca_generate = infinite_generate; break;  
+    case CYCLIC: s->ca_generate = cyclic_generate; break;
+    }
+
+    switch (s->ca_bass_name) {
+    case B_LOWEST_NOTES: s->ca_bass = ca_bass_lowest_notes; break;
+    case B_LOWER_EIGHTH: s->ca_bass = ca_bass_lower_eighth; break; 
+    }
+
+    switch (s->ca_chords_name) {
+    case C_EIGHTH: s->ca_chords = ca_chords_eighth; break;
+    case C_WHOLE: s->ca_chords = ca_chords_whole; break;
+    }    
+    
+    switch (s->ca_lead_name) {
+    case L_UPPER_EIGHTH: s->ca_lead = ca_lead_upper_eighth; break;
+    case L_UPPER_WHOLE: s->ca_lead = ca_lead_upper_whole; break;
+    case L_LOWER_EIGHTH: s->ca_lead = ca_lead_lower_eighth; break;
+    case L_LOWER_WHOLE: s->ca_lead = ca_lead_lower_whole; break;
+    }
+
+    if (!(s->p_instr = av_malloc(s->p_maxres * sizeof(int))))
+        return AVERROR(ENOMEM);
+    if (!(s->p_beats = av_malloc(s->p_maxres * sizeof(int))))
+        return AVERROR(ENOMEM);    
+    memset(s->p_instr, 0, s->p_maxres * sizeof(int));
+    memset(s->p_beats, 0, s->p_maxres * sizeof(int));
+    
+    switch (s->p_algorithm) {
+        case PADRIDDLE: padriddle(s); break;
+        case ALTERNATE: alternate(s); break;
+        case TOGGLE: toggle(s); break;
+        case ALTPAD: alternate_n_padriddle(s); break;
+        case TOGPAD: toggle_n_padriddle(s); break;
+        case TOGALT: alternate_n_toggle(s); break;
+    }
+
+    switch (s->algorithm) {
+    case RIFFS: s->schedule_pattern = schedule_riff_pattern; break;
+    case LSYSTEM: schedule_0L_pattern(s); s->schedule_pattern = schedule_L_pattern; break;
+    case CA: s->schedule_pattern = schedule_ca_pattern; break;
+    case RHYTHM: s->schedule_pattern = schedule_r_pattern; break;
+    }
+
+    instrument_select(find_instrument(s->instrument, s), s->time_marker, RIFFNL, s);
+    instrument_select(find_instrument(s->bass_instr, s), s->time_marker, CA_BASS, s);
+    instrument_select(find_instrument(s->chords_instr, s), s->time_marker, CA_CHORDS, s);
+    instrument_select(find_instrument(s->lead_instr, s), s->time_marker, CA_LEAD, s);
+
+    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->riffs);
+    av_freep(&s->prevgen);
+    av_freep(&s->nextgen);
+    av_freep(&s->system);
+    av_freep(&s->ca_ruleset);
+    av_freep(&s->ca_neighbours);
+    av_freep(&s->note_map);
+    av_freep(&s->scale);
+    av_freep(&s->p_instr);
+    av_freep(&s->p_beats);
+    for (int k = 0; k < 8; k++)
+        av_freep(&s->ca_8keys[k]);
+}
+
+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;
+}
+
+static int activate(AVFilterContext *ctx)
+{
+    AVFilterLink *outlink = ctx->outputs[0];
+    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) {
+        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,
+        .config_props  = config_props,
+    },
+    { NULL }
+};
+
+AVFilter ff_asrc_atone = {
+    .name          = "atone",
+    .description   = NULL_IF_CONFIG_SMALL("Generate algorithmic music."),
+    .query_formats = query_formats,
+    .init          = init,
+    .uninit        = uninit,
+    .activate      = activate,
+    .priv_size     = sizeof(AtoneContext),
+    .inputs        = NULL,
+    .outputs       = atone_outputs,
+    .priv_class    = &atone_class,
+};
+
+
diff --git a/libavfilter/notedef.h b/libavfilter/notedef.h
new file mode 100644
index 0000000000..d77b3622f3
--- /dev/null
+++ b/libavfilter/notedef.h
@@ -0,0 +1,269 @@ 
+/*
+ * 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_NOTEDEF_H
+#define AVFILTER_NOTEDEF_H
+#include <stdlib.h>
+#include<string.h>
+
+/*Define notes as per the General Midi specifications 
+*_ = minus, s = sharp, b = flat
+*   H = hold tone, R = Rest*/
+enum notes { C_1, Cs_1, Db_1 = 1, D_1, Ds_1, Eb_1 =3, E_1, F_1, Fs_1, Gb_1 = 6, G_1, Gs_1, Ab_1 = 8, A_1, As_1, Bb_1 =10, B_1,
+            C0, Cs0, Db0 = 13, D0, Ds0, Eb0 = 15, E0, F0, Fs0, Gb0 = 18, G0, Gs0, Ab0 = 20, A0, As0, Bb0 = 22, B0,
+            C1, Cs1, Db1 = 25, D1, Ds1, Eb1 = 27, E1, F1, Fs1, Gb1 = 30, G1, Gs1, Ab1 = 32, A1, As1, Bb1 = 34, B1,
+            C2, Cs2, Db2 = 37, D2, Ds2, Eb2 = 39, E2, F2, Fs2, Gb2 = 42, G2, Gs2, Ab2 = 44, A2, As2, Bb2 = 46, B2,
+            C3, Cs3, Db3 = 49, D3, Ds3, Eb3 = 51, E3, F3, Fs3, Gb3 = 54, G3, Gs3, Ab3 = 56, A3, As3, Bb3 = 58, B3,
+            C4, Cs4, Db4 = 61, D4, Ds4, Eb4 = 63, E4, F4, Fs4, Gb4 = 66, G4, Gs4, Ab4 = 68, A4, As4, Bb4 = 70, B4,
+            C5, Cs5, Db5 = 73, D5, Ds5, Eb5 = 75, E5, F5, Fs5, Gb5 = 78, G5, Gs5, Ab5 = 80, A5, As5, Bb5 = 82, B5,
+            C6, Cs6, Db6 = 85, D6, Ds6, Eb6 = 87, E6, F6, Fs6, Gb6 = 90, G6, Gs6, Ab6 = 92, A6, As6, Bb6 = 94, B6,
+            C7, Cs7, Db7 = 97, D7, Ds7, Eb7 = 99, E7, F7, Fs7, Gb7 = 102, G7, Gs7, Ab7 = 104, A7, As7, Bb7 = 106, B7,
+            C8, Cs8, Db8 = 109, D8, Ds8, Eb8 = 111, E8, F8, Fs8, Gb8 = 114, G8, Gs8, Ab8 = 116, A8, As8, Bb8 = 118, B8,
+            C9, Cs9, Db9 = 121, D9, Ds9, Eb9 = 123, E9, F9, Fs9, Gb9 = 126, G9, H, R};
+
+const char *GM_instrument_list[128] = {"Acoustic-Grand", "Bright-Acoustic", "Electric-Grand", "Honky-Tonk", "Electric-Piano-1", "Electric-Piano-2", 
+"Harpsichord", "Clav", "Celesta", "Glockenspiel", "Music-Box", "Vibraphone", "Marimba", "Xylophone", "Tubular-Bells", "Dulcimer", "Drawbar-Organ", 
+"Percussive-Organ", "Rock-Organ", "Church-Organ", "Reed-Organ", "Accordion", "Harmonica", "Tango-Accordion", "Acoustic-Guitar-nylon", "Acoustic-Guitar-steel", 
+"Electric-Guitar-jazz","Electric-Guitar-clean", "Electric-Guitar-muted", "Overdriven-Guitar", "Distortion-Guitar", "Guitar-Harmonics",
+"Acoustic-Bass", "Electric-Bass-finger", "Electric-Bass-pick", "Fretless-Bass", "Slap-Bass-1", "Slap-Bass-2", "Synth-Bass-1", "Synth-Bass-2",
+ "Violin", "Viola", "Cello", "Contrabass", "Tremolo-Strings", "Pizzicato-Strings", "Orchestral-Harp", "Timpani", "String-Ensemble-1", "String-Ensemble-2", 
+ "SynthStrings-1", "SynthStrings-2", "Choir-Aahs", "Voice-Oohs", "Synth-Voice", "Orchestra-Hit", "Trumpet", "Trombone", "Tuba",
+ "Muted-Trumpet", "French-Horn", "Brass-Section", "SynthBrass-1", "SynthBrass-2", "Soprano-Sax", "Alto-Sax", "Tenor-Sax", "Baritone-Sax", 
+ "Oboe", "English-Horn", "Bassoon", "Clarinet", "Piccolo", "Flute", "Recorder", "Pan-Flute", "Blown-Bottle", "Shakuhachi", "Whistle", "Ocarina", 
+ "Lead-1-square", "Lead-2-sawtooth", "Lead-3-calliope", "Lead-4-chiff", "Lead-5-charang", "Lead-6-voice", "Lead-7-fifths", "Lead-8-bass+lead", 
+ "Pad-1-new-age", "Pad-2-warm", "Pad-3-polysynth", "Pad-4-choir", "Pad-5-bowed", "Pad-6-metallic", "Pad-7-halo", "Pad-8-sweep", 
+ "FX-1-rain", "FX-2-soundtrack", "FX-3-crystal", "FX-4-atmosphere", "FX-5-brightness", "FX-6-goblins", "FX-7-echoes", "FX-8-sci-fi",
+  "Sitar", "Banjo", "Shamisen", "Koto", "Kalimba", "Bagpipe", "Fiddle", "Shanai", "Tinkle-Bell", "Agogo", "Steel-Drums", "Woodblock", "Taiko-Drum",
+   "Melodic-Tom", "Synth-Drum", "Reverse-Cymbal", "Guitar-Fret-Noise", "Breath-Noise", "Seashore", "Bird-Tweet", "Telephone-Ring", "Helicopter", 
+   "Applause", "Gunshot"};
+
+enum percussion_notes{Metronome_Click = 33, Metronome_Bell, Acoustic_Bass_Drum,  Bass_Drum_1,  Side_Stick,  Acoustic_Snare,  Hand_Clap,  Electric_Snare,  Low_Floor_Tom, 
+ Closed_Hi_Hat,  High_Floor_Tom,  Pedal_Hi_Hat,  Low_Tom,  Open_Hi_Hat,  Low_Mid_Tom,  Hi_Mid_Tom,  Crash_Cymbal_1,  High_Tom,  Ride_Cymbal_1,  Chinese_Cymbal,
+  Ride_Bell, Tambourine,  Splash_Cymbal, Cowbell,  Crash_Cymbal_2, Vibraslap,  Ride_Cymbal_2, Hi_Bongo,  Low_Bongo,  Mute_Hi_Conga,  Open_Hi_Conga,  Low_Conga, 
+   High_Timbale,  Low_Timbale,  High_Agogo,  Low_Agogo, Cabasa, Maracas,  Short_Whistle,  Long_Whistle,  Short_Guiro,  Long_Guiro, Claves,  Hi_Wood_Block,  
+   Low_Wood_Block, Mute_Cuica,  Open_Cuica,  Mute_Triangle, Open_Triangle};
+
+/*Assuming maximum of three percussion instruments can be played at the same time*/
+/*Define some drum beats...
+Beat: Whole note = 1, Half note = 2, Quater note = 4, ..., Number of beats: Whole note = 4/1, Half note = 4/2, Quater note = 4/4
+Note 1 does not produce any sound*/
+/*In tracks the 4 * i + 0 element is instrument1
+4 * i + 1 element is instrument2
+4 * i + 2 element is instrument3
+4 * i + 3 element is beat*/
+const int Track1[] = {Bass_Drum_1, Ride_Cymbal_2, 1, 12, 
+                    1, 1, 1, 12, 
+                    Bass_Drum_1, 1, 1, 12, 
+                    Electric_Snare, Ride_Cymbal_2, Pedal_Hi_Hat, 12,
+                    1, 1, 1, 12,
+                    Electric_Snare, Ride_Cymbal_2, 1, 12, 
+                    Bass_Drum_1, Ride_Cymbal_2, 1, 12, 
+                    1, 1, 1, 12, 
+                    Bass_Drum_1, 1, 1, 12, 
+                    Electric_Snare, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    Electric_Snare, Ride_Cymbal_2, 1, 12};
+
+const int Track2[] = {1, Ride_Cymbal_2, 1, 12, 
+                    1, 1, 1, 12, 
+                    Bass_Drum_1, 1, 1, 12, 
+                    Electric_Snare, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    Bass_Drum_1, Ride_Cymbal_2, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12, 
+                    1, 1, 1, 12, 
+                    Bass_Drum_1, 1, 1, 12, 
+                    Electric_Snare, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    Bass_Drum_1, Ride_Cymbal_2, 1, 12};
+
+const int Track3[] = {1, Ride_Cymbal_2, 1, 12,
+                    1, 1, 1, 12, 
+                    1, 1, 1, 12, 
+                    1, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12, 
+                    Electric_Snare, 1, 1, 12, 
+                    Electric_Snare, 1, 1, 12, 
+                    1, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12};
+
+const int Track4[] = {1, Ride_Cymbal_2, 1, 12, 
+                    Electric_Snare, 1, 1, 12, 
+                    Electric_Snare, 1, 1, 12, 
+                    1, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12, 
+                    Electric_Snare, 1, 1, 12, 
+                    Electric_Snare, 1, 1, 12, 
+                    1, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12};
+
+const int Track5[] = {Electric_Snare, Ride_Cymbal_2, 1, 12, 
+                    Electric_Snare, 1, 1, 12, 
+                    Bass_Drum_1, 1, 1, 12, 
+                    1, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12, 
+                    Electric_Snare, Ride_Cymbal_2, 1, 12, 
+                    Electric_Snare, 1, 1, 12, 
+                    Bass_Drum_1, 1, 1, 12, 
+                    1, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12};
+
+const int Track6[] = {1, Ride_Cymbal_2, 1, 12, 
+                    1, 1, 1, 12, 
+                    Electric_Snare, 1, 1, 12,
+                    1, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    Electric_Snare, 1, 1, 12, 
+                    Electric_Snare, Ride_Cymbal_2, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12, 
+                    1, 1, 1, 12, 
+                    Bass_Drum_1, 1, 1, 12, 
+                    Electric_Snare, Ride_Cymbal_2, Pedal_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, Ride_Cymbal_2, 1, 12};
+
+const int Track7[] = {Bass_Drum_1, 1, Closed_Hi_Hat, 8,
+                    1, 1, Closed_Hi_Hat, 8, 
+                    Acoustic_Snare, 1, Closed_Hi_Hat, 8, 
+                    1, 1, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    Acoustic_Snare, 1, Closed_Hi_Hat, 8, 
+                    1, 1, Closed_Hi_Hat, 8};
+
+const int Track8[] = {Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    Acoustic_Snare, 1, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    1, 1, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    1, 1, Closed_Hi_Hat, 8};
+
+const int Track9[] = {Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    Acoustic_Snare, 1, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    1, 1, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    Acoustic_Snare, 1, Closed_Hi_Hat, 8, 
+                    1, 1, Closed_Hi_Hat, 8};
+
+const int Track10[] = {Bass_Drum_1, Acoustic_Snare, Closed_Hi_Hat, 8, 
+                    1, 1, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, Acoustic_Snare, Closed_Hi_Hat, 8, 
+                    1, 1, Closed_Hi_Hat, 8, 
+                    1, Acoustic_Snare, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8, 
+                    1, Acoustic_Snare, Closed_Hi_Hat, 8, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 8};
+
+const int Track11[] = {Bass_Drum_1, 1, Closed_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, 1, Closed_Hi_Hat, 12, 
+                    Acoustic_Snare, 1, Closed_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, 1, Closed_Hi_Hat, 12, 
+                    Bass_Drum_1, 1, Closed_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, 1, Closed_Hi_Hat, 12, 
+                    Acoustic_Snare, 1, Closed_Hi_Hat, 12, 
+                    1, 1, 1, 12, 
+                    1, 1, Closed_Hi_Hat, 12};
+
+const int Track12[] = {Metronome_Click, 1, 1, 4, 
+                        Metronome_Click, 1, 1, 4, 
+                        Metronome_Click, 1, 1, 4, 
+                        Metronome_Click, 1, 1, 4};
+
+const char *percussion_tracks[] = {"Jazz1", "Jazz2", "Jazz3", "Jazz4", "Jazz5", "Jazz6", "Rock1", "Rock2", "Rock3", "Rock4", "Shuffle", "Metronome"};
+
+#define MAX_TRACK_SIZE 144
+/*Define the riffs : 8 notes per riff
+Reference: http://peterlangston.com/Papers/amc.pdf */
+#define NPR 8 
+const int riff[] = {Eb4,  D4,  A4,  F4,  E4,  C5,  A4,  A4,  /*  0 */
+                F4,  A4, Eb5,  D5,  E4,  A4,  C5,  A4,  /*  1 */
+                Ab4,  A4,   H,  G5,   H,  Eb5,  C5,  E5,  /*  2 */
+                Ab4,  A4,  B4,  C5, Eb5,  E5, Ab5,  A5,  /*  3 */
+                A4,  Bb4,  B4,  C5, Db5,  D5, Eb5,  E5,  /*  4 */
+                A4,  Bb4,  B4,  C5,  E5, Eb5,  D5,  C5,  /*  5 */
+                A4,  B4,  C5,  A4,  B4,  C5,  D5,  B4,  /*  6 */
+                A4,  B4,  C5,  D5, Eb5,  E5, Eb5,  C5,  /*  7 */
+                A4,  C5,  D5, Eb5,  Gb5,  Ab5,  A5,  C6,  /*  8 Pat  Metheny  */
+                A4,  C5, Eb5,  B4,  D5,  F5, Eb5,  C5,  /*  9 */
+                A4,  C5,  E5,  G5,  B5,  A5,  G5,  E5,  /* 10  */
+                A4,  C5,  E5,  A5,  G5, Eb5,  C5,  A4,  /* 11  */
+                B4,  A4,  B4,  C5,  B4,  A4,  B4,  C5,  /* 12  */
+                B4,  A4,  B4,  C5,  B4,  C5,  B4,  A4,  /* 13  */
+                B4,  A4,  B4,  C5,  D5,  C5,  D5, Eb5,  /* 14  */
+                C5, Ab4,  A4,  G5,  F5, Gb5, Eb5,  E5,  /* 15 Marty Cutler */
+                C5,  D5,  C5,  B4,  C5,  B4,  A4,   H,  /* 16  */
+                C5,  D5, Eb5,  C5,  D5, Eb5,  F5,  D5,  /* 17  */
+                D5,  C5,  A4,  C5,  E5, Eb5,  D5,  C5,  /* 18  */
+                D5,  C5,  D5, Eb5,  D5,  C5,  D5, Eb5,  /* 19  */
+                D5,  Eb5,  E5,  F5, Gb5,  G5, Ab5,  A5,  /* 20  */
+                D5, Eb5,  G5, Eb5,  D5,  C5,  B4,  C5,  /* 21 Charlie Keagle */
+                D5,  Eb5,  A5,  D5,   H,  C5,  A4,  E4,  /* 22  */
+                D5,  E5,  G5,  E5,  C5,   H,  D5,  A5,  /* 23  Lyle  Mays/Steve  Cantor  */
+                Eb5,  D5, Eb5,  D5,   H,  C5,  A4,   H,  /* 24  */
+                Eb5,  D5, Eb5,  F5, Eb5,  D5,  C5,  B4,  /* 25  */
+                Eb5,  E5,  D5,  C5,  B4,  A4, Ab4,  A4,  /* 26  Richie  Shulberg  */
+                Eb5,  E5,  A5,  C5,  B4,  E5,  A4,  A4,  /* 27  */
+                Eb5,  Gb5,  E5,  A4,  B4,  D5,  C5,  E4,  /* 28  Django  Rheinhart  */
+                E5,  A4,  C5, Ab4,  B4,  G4, Gb4,  E4,  /* 29  David  Levine  */
+                E5,  Eb5,  D5,  C5,  B4,  C5,  D5,  F5,  /* 30  */
+                G5,  E5,  D5,  B4, Eb5,   H,  C5,  A4,  /* 31  */
+                G5,  E5,  D5, Gb5,  C5,   H,  A4,   H,  /* 32  Mike  Cross  */
+                Ab5,  A5, Ab5,  A5, Ab5,  A5, Ab5,  A5,  /* 33  Django  Rheinhart  */
+                A5,  E5,  C5,  G4,  C5,  E5,  A5,  A5,  /* 34  Django  Rheinhart  */
+                A5,  E5,  C5,  A4,  G5, Eb5,  C5,  A4,  /* 35  */
+                A5,  B5,  G5,  E5,  F5, Gb5,  G5, Ab5,  /* 36  */
+                B5,  C6,  A5,  E5,  G5,  B5,  A5,   H,  /* 37  */
+                B5,  D6,  C6,  E5, Ab5,  B5,  A5,  C5,  // 38  Django  Rheinhart  
+                C6,  B5,  A5,  G5, Gb5,  E5, Eb5,  C5} ;/* 39  */
+
+typedef struct {
+    int note;
+    int dur;
+} lsys;
+
+#define L_MAX_LENGTH 65536
+
+/*Define Scale Intervals*/
+const int major_increment[] = {2, 2, 1, 2, 2, 2};
+const int natural_minor_increment[] = {2, 1, 2, 2, 1, 2};
+const int melodic_minor_increment[] = {2, 1, 2, 2, 2, 2};
+const int harmonic_minor_increment[] = {2, 1, 2, 2, 1, 3};
+const int major_pentatonic_increment[] = {2, 2, 3, 2};
+const int minor_pentatonic_increment[] = {3, 2, 2, 3};
+const int blues_increment[] = {3, 2, 1, 1, 3};
+
+const int drums[] = {Bass_Drum_1, Acoustic_Bass_Drum, Acoustic_Snare, Electric_Snare};
+const int toms[] = {Low_Floor_Tom, Low_Mid_Tom, Low_Tom, Hi_Mid_Tom, High_Floor_Tom, High_Tom};
+const int cymbals[] = {Crash_Cymbal_1, Crash_Cymbal_2, Ride_Cymbal_1, Ride_Cymbal_2, Chinese_Cymbal, Splash_Cymbal};
+const int hi_hats[] = {Pedal_Hi_Hat, Closed_Hi_Hat, Open_Hi_Hat};
+
+#endif/*AVFILTER_NOTEDEF_H*/ 
+
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 308fbe07c3..b8ba489da7 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  87
+#define LIBAVFILTER_VERSION_MINOR  88
 #define LIBAVFILTER_VERSION_MICRO 100