How to Crossfade
  • Hello,

    This is a small tutorial on how to crossfade with liquidsoap. I have muddled around for almost a week before figuring this out. Perhaps this will help someone in the future. Tested on Airtime 2.1.3

    Add the following lines to your /usr/lib/airtime/pypo/bin/liquidsoap_scripts/ls_script.liq just under the line "%include "ls_lib.liq""

    def my_fade (~start_next=3.,~fade_in=3.,~fade_out=3.,~width=1.,~conservative=true,s)
    mf_high = 20.

    mf_medium = 32.

    mf_margin = 4.

    fade.out = fade.out(duration=fade_out)
    fade.in = fade.in(duration=fade_in)

    add = fun (from,to) ->
    add(normalize=false,

    [ to,from ])


    log = log(label="my_fade")
    def transition (a, b, ma, mb, sa, sb)

    if


    (a + mf_high >= 0. and b + mf_high >= 0.) or


    (a + mf_medium >= 0. and b + mf_medium >= 0. and abs(a - b) <= mf_margin)


    then


    log("No transition, just sequencing.")


    sequence([sa, sb])



    elsif


    a + mf_medium <= 0. and b + mf_medium >= 0. and abs(a - b) <= mf_margin


    then


    log("Using transition 1: crossed.")


    add(fade.out(sa),fade.in(sb))

    elsif

    b >= a + mf_margin and a <= mf_high


    then


    log("Using transition 2: crossed, fade-out.")


    add(fade.out(sa),sb)

    elsif

    a >= b + mf_margin and b <= mf_high


    then


    log("Using transition 3: crossed, fade-in.")


    add(sa,fade.in(sb))

    else

    log("Using transition 4: crossed, fade-in, fade-out.")


    add(fade.out(sa),fade.in(sb))


    end


    end

    smart_cross(transition,width=width,duration=start_next,conservative=conservative,s)

    end


    now look for the line  "queue = map_metadata(append_title, queue)"
    and add this line under it:

    queue = my_fade(queue)

    Thats it. Restart your server or the playout service with

    sudo service airtime-playout restart

    Crossfading should now work based on the values of: ~start_next=3.,~fade_in=3.,~fade_out=3.,~width=1
    You may edit these values to suit your needs. The script uses a smart crossfade by checking the relative volumes of the current track and the next track and applies an effect accordingly.

    I have not written this script. It was taken from the dolebrai script which I found on the liquidsoap site.
    Post edited by Anand Kapre at 2012-07-23 14:36:40
  • 3 Comments sorted by
  • This will defn help some of our users. The only downside of this script is that the user cannot customize their crossfades on a per-track basis. This is something that is being worked on and should be available in future versions of Airtime :)
    Airtime Pro Hosting: http://airtime.pro
  • this not working anymore in 2.2.0? i tried and nothing happened
  • %include "ls_lib.liq"

    # Crossfade between tracks, 
    # taking the respective volume levels 
    # into account in the choice of the 
    # transition.
    # @category Source / Track Processing
    # @param ~start_next   Crossing duration, if any.
    # @param ~fade_in      Fade-in duration, if any.
    # @param ~fade_out     Fade-out duration, if any.
    # @param ~width        Width of the volume analysis window.
    # @param ~conservative Always prepare for
    #                      a premature end-of-track.
    # @param s             The input source.
    def smart_crossfade (~start_next=3.,~fade_in=3.,
                         ~fade_out=3., ~width=2.,
                 ~conservative=false,s)
      high   = -20.
      medium = -32.
      margin = 4.
      fade.out = fade.out(type="sin",duration=fade_out)
      fade.in  = fade.in(type="sin",duration=fade_in)
      add = fun (a,b) -> add(normalize=false,[b,a])
      log = log(label="smart_crossfade")

      def transition(a,b,ma,mb,sa,sb)

        list.iter(fun(x)-> 
           log(level=4,"Before: #{x}"),ma)
        list.iter(fun(x)-> 
           log(level=4,"After : #{x}"),mb)

        if
          # If A and B and not too loud and close, 
          # fully cross-fade them.
          a <= medium and 
          b <= medium and 
          abs(a - b) <= margin
        then
          log("Transition: crossed, fade-in, fade-out.")
          add(fade.out(sa),fade.in(sb))

        elsif
          # If B is significantly louder than A, 
          # only fade-out A.
          # We don't want to fade almost silent things, 
          # ask for >medium.
          b >= a + margin and a >= medium and b <= high
        then
          log("Transition: crossed, fade-out.")
          add(fade.out(sa),sb)

        elsif
          # Do not fade if it's already very low.
          b >= a + margin and a <= medium and b <= high
        then
          log("Transition: crossed, no fade-out.")
          add(sa,sb)

        elsif
          # Opposite as the previous one.
          a >= b + margin and b >= medium and a <= high
        then
          log("Transition: crossed, fade-in.")
          add(sa,fade.in(sb))

        # What to do with a loud end and 
        # a quiet beginning ?
        # A good idea is to use a jingle to separate 
        # the two tracks, but that's another story.

        else
          # Otherwise, A and B are just too loud 
          # to overlap nicely, or the difference 
          # between them is too large and 
          # overlapping would completely mask one 
          # of them.
          log("No transition: just sequencing.")
          sequence([sa, sb])
        end
      end

      smart_cross(width=width, duration=start_next, 
                  conservative=conservative,
                  transition,s)
    end

    web_stream = input.harbor("test-harbor", port=8999, password=stream_harbor_pass)
    web_stream = on_metadata(notify_stream, web_stream)
    output.dummy(fallible=true, web_stream)


    # the crossfade function controls fade in/out
    queue = smart_crossfade(queue)
    queue = crossfade_airtime(queue)
    queue = on_metadata(notify, queue)
    queue = map_metadata(update=false, append_title, queue)
    output.dummy(fallible=true, queue)d_title, queue)
    output.dummy(fallible=true, queue)

    Any idea why this is not working in ls_script.liq? 
    Post edited by Topea at 2012-11-07 11:51:44