Liquidsoap has a feature called 'Smart crossfade'.
This feature includes the following functionality as described in their documentation:
Liquidsoap includes an advanced crossfading operator. Using it, you can code which transition you want for your songs, according to the average volume level (in dB) computed on the end of the ending track and the beginning of the new one.
Currently, it is only possible to define the crossfade duration in AzuraCast.
What I had in mind, was adding a switch which you can enable to use the smart crossfade function. This makes it possible for users without knowledge about Liquidsoap's scripting language to use this neat feature.
// Edit
Link to the documentation: https://www.liquidsoap.info/doc-dev/smartcrossfade.html
Just found out about this feature on the Liquidsoap website and then I found your post here. Really think it would be a welcome enhancement as the build in cross fading settings can be ugly with adjacent loud starting and ending audio.
Should you have any luck with configuring this in the AutoDJ configuration part (bottom of the page where extra liquidsoap code can be added) then I would really love to hear that!
@AmsterdamFM It is possible to add it by pasting in the smart_crossfade script into your custom auto DJ configuration. Mine looks like this:
# 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=5.,~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
radio = smart_crossfade(start_next=5., fade_in=3., fade_out=3., width=2., conservative=false, radio)
radio = nrj(radio)
Done!
Smart sounds a lot better! Thank you for sharing. Hope this will become a build in feature so more people can profit from better sounding transitions.
@bjarn @AmsterdamFM Smart crossfade is now built in to AzuraCast. You can now set your crossfade mode as either 'Smart mode', 'Normal mode' or 'Disabled'.
Most helpful comment
@bjarn @AmsterdamFM Smart crossfade is now built in to AzuraCast. You can now set your crossfade mode as either 'Smart mode', 'Normal mode' or 'Disabled'.