savonet / liquidsoap

Liquidsoap is a statically typed scripting general-purpose language with dedicated operators and backend for all thing media, streaming, file generation, automation, HTTP backend and more.
http://liquidsoap.info
GNU General Public License v2.0
1.4k stars 130 forks source link

Pop/click at the end of fade out in 2.2.0 #3318

Closed Thaam closed 9 months ago

Thaam commented 1 year ago

Describe the bug In 2.2.0, there is a pop/click at the end of the fade out while crossfading. In 2.1.4, there is no issue when crossfade is used.

Log from 2.2.0: 2023/08/15 05:48:16 [cross_before.3:4] Fading out with type sin, duration: 3. and 2.97267573696s remaining.

Log from 2.1.4: 2023/08/15 06:07:53 [cross_0_before:4] Fading out with 3.s remaining.

To Reproduce stream = playlist("/home/benoit/devel/liquidsoap/music_test") stream = crossfade(stream) output.pulseaudio(mksafe(stream))

Expected behavior No pop/click while crossfading.

Version details

Install method Packages downloaded from github:

https://github.com/savonet/liquidsoap/releases/download/v2.2.0/liquidsoap_2.2.0-debian-bookworm-1_amd64.deb https://github.com/savonet/liquidsoap/releases/download/v2.1.4/liquidsoap_2.1.4-debian-bookworm-1_amd64.deb

toots commented 1 year ago

Thanks for reporting. I'll have a look shortly.

toots commented 1 year ago

We found and fixed a pretty subtile yet bad bug where the muxer (used in a lot of operators now with tracks) was leaking audio. This might have caused this issue.

Would you be able to test the latest rolling release: https://github.com/savonet/liquidsoap/releases/tag/rolling-release-v2.2.x ?

Thaam commented 1 year ago

I still have the clicks with the Liquidsoap 2.2.1+git@46968a5ac version.

gAlleb commented 1 year ago

opam 2.2.1 Still hearing clicks with the following settings: crossfade(smart = false, fade_out=3.00, fade_in=0.00, duration=3.00)

caturria commented 1 year ago

Just chiming in to say that I also experience clicks at the end of transitions (the "new" source seems to jump forward a fraction of a second). It's not specific to crossfading; it'll happen even if the transition is a simple add.

gAlleb commented 1 year ago

It's not specific to crossfading; it'll happen even if the transition is a simple add.

since crossfade is an add-based operator it makes sense.

caturria commented 1 year ago

I don't know if this is related, but I also have several tracks that pop and click constantly when played back in this version. I checked them for clipping, tried disabling all post-processing, no cigar. They play back fine in other players, even in older versions of Liquidsoap. But in this version, they click and pop every couple of seconds (in addition to the clicks and pops at the end of transitions).

toots commented 1 year ago

I'm gonna have another pass at this very shortly. Is there any chance any of y'all would have a simple reproduction script to share, possibly with the associated files (can be sent in private). Thks!

caturria commented 1 year ago

If the OP hasn't already responded to this, I can get you something this aft. Pretty much any two tracks should do as it seems to be pretty consistent.

toots commented 1 year ago

If the OP hasn't already responded to this, I can get you something this aft. Pretty much any two tracks should do as it seems to be pretty consistent.

That would be awesome! You can email me at: toots@rastageeks.org

caturria commented 1 year ago

Email sent; thank you.

gAlleb commented 1 year ago

@caturria @toots Thank you!

If it would help could you reproduce with this too? crossfade(smart = false, fade_out=3.00, fade_in=0.00, duration=3.00, s) I've tried two settings. Strangely enough with the above setting I hear "clicks".

But with crossfade (smart = false, fade_out=0., fade_in=3., duration=4., s) no "clicks. Probably because here fade_out is fade_out=0..

caturria commented 1 year ago

I use fade_out = 0, fade_in = 0, duration > 0 (so cross-only). I still get clicks.

gAlleb commented 1 year ago

Well, clearly then @toots should look at it closely. Thanks.

caturria commented 1 year ago

What it sounds like to me is that Liquidsoap buffers a bit too much audio during the transition, which gets thrown away when the transition ends. I tried making cross_duration an exact multiple of the frame duration thinking I could maybe work around it, but that didn't work. I also sent @Toots an example of a track that doesn't play back correctly in this version of Liquidsoap (but sounds normal in other players / older Liquid versions). I don't know if it's related, but it's the same thing; pops and clicks.

caturria commented 1 year ago

Hi @Toots, I was just wondering if you are able to reproduce it on your end with the samples I provided?

toots commented 1 year ago

Hi all, I got both reproduction scripts and I'm looking at them right now. No luck so far but I haven't had much time to look at them yet.

caturria commented 1 year ago

By that, do you mean they don't reproduce clicks on your end?

toots commented 1 year ago

Not yet. I am testing across versions. Just to make sure, @caturria, you confirm that the clicks are still present with 2.2.1?

caturria commented 1 year ago

I confirm. caturria@caturria:~/ls_test$ liquidsoap --version
Liquidsoap 2.2.1+dev
Copyright (c) 2003-2023 Savonet team
Liquidsoap is open-source software, released under GNU General Public License.
See http://liquidsoap.info for more information. Clicks on transition script:

radio = single("annotate:liq_cue_in=185,liq_fade_in=0.0,liq_fade_out=0.0,liq_cross_duration=7.0:Houdini.flac") radio = cue_cut(radio) radio = crossfade(radio) output.file(fallible=true, %mp3, "clicks_on_transition.mp3", radio);

Result: https://cloud.caturria.ca/s/eLe362PWqbrF3Kq

Note: the transition is seven seconds long, and the click is right at the end of it (seven seconds after the track loops around).

Clicks in track that plays correctly in previous versions / other software:

radio = single("MOT () - cloudy SEOUL( ).ogg") output.file(fallible=true, %mp3, "cloudy_clicking_seoul.mp3", radio);

Result: https://cloud.caturria.ca/s/s5ZR2TdASn7dK38 Clicks are constant. I sent you the source track; you'll hear that it doesn't play like that in other players.

toots commented 1 year ago

I was able to reproduce. thanks y'all.

caturria commented 1 year ago

That's wonderful, thank you. You are able to produce both of them?

toots commented 1 year ago

I think so. I'm focusing on @Thaam example to begin with, most likely the same problem. I've got my finger on it, let's see if I can fix it quickly..

toots commented 1 year ago

Hi there! I was able to track this down to an issue that probably has been present for a while but wasn't really visible until we started relying on cached sources extensively with the introduction of the muxing operator.

If y'all want to try the fix-3318 or the assets that should build here: https://github.com/savonet/liquidsoap/actions/runs/6282503009 I'm pretty sure that this fixes the issue.

This is a pretty important (and subtle!) issue so I will fast-track another bugfix release with it shortly. Thanks for reporting, sending reproduction scripts and y'all patience overall!

Thaam commented 1 year ago

Hi,

I've compiled the fix-3318 version and when fading to the second song, no more sound and I have this error with an infinite loop:

2023/09/23 12:53:33 [cross_after:4] Fading in with type: sin and duration: 3.s. 2023/09/23 12:53:35 [cross_before:4] Fading out with type sin, duration: 3. and 2.99904761905s remaining. 2023/09/23 12:53:36 [clock.pulseaudio:2] We must catchup 0.30 seconds! 2023/09/23 12:53:38 [buffer:4] End of track. 2023/09/23 12:53:38 [buffer:4] Buffer emptied, buffering needed. 2023/09/23 12:53:38 [cross_before:4] Fading out with type sin, duration: 3. and 0.s remaining. 2023/09/23 12:53:38 [cross_before:4] Fading out with type sin, duration: 3. and 0.s remaining. 2023/09/23 12:53:38 [cross_before:4] Fading out with type sin, duration: 3. and 0.s remaining. 2023/09/23 12:53:38 [cross_before:4] Fading out with type sin, duration: 3. and 0.s remaining.

The complete log is here: https://pastebin.com/ZCm45GLC

toots commented 1 year ago

Yeah my fix was premature.. the branch has been updated and looks more promised now. The assets are also built here: https://github.com/savonet/liquidsoap/actions/runs/6289670271

Thaam commented 1 year ago

Maybe @caturria can confim but for me the issue is resolved with Liquidsoap 2.3.0+git@f0f100c28

Thank you.

caturria commented 1 year ago

I'll give it a spin today and let you know. Thank you for your attention to this.

caturria commented 1 year ago

Hi, I also confirm that this commit fixes the issue for me. Thank you very much. @Toots, I have created another issue with regards to the track I sent you which plays back incorrectly: https://github.com/savonet/liquidsoap/issues/3429 Thank you.

toots commented 1 year ago

This fix has been backported to rolling-release-v2.2.x and will be released in a short time frame: https://github.com/savonet/liquidsoap/commit/6e9c2c0212b1eb10acd46901b0a1542ab835e526

gAlleb commented 10 months ago

liquidsoap 2.2.3 Ububntu 22.04 opam Following https://github.com/AzuraCast/AzuraCast/issues/6749 clicks/pops still persist at the end of fade_out.

crossfade(smart = false, fade_out=3.50, fade_in=0.00, duration=4.00, s)

In azuracast too.

def live_aware_crossfade(old, new) =
    if to_live() then
        sequence([fade.out(old.source),fade.in(new.source)])
    else
        cross.simple(old.source, new.source, fade_in=0.0, fade_out=3.50)
    end
end
radio = cross(minimum=0.00, duration=4.00, live_aware_crossfade, radio)

You clearly can hear them especially when the beginning of the next song is quiet and no post processing is applied. So maybe issue should be reopened.

Or I'm just going mad and starting to hear pops and clicks everywhere :))

Without jokes: one can definitely hear them. So it is kinda strange that not a lot of folks bring up this issue.

pozhiloy-enotik commented 10 months ago

@toots

gAlleb commented 10 months ago

Made a quick example. Here is script

test_playlist = playlist(reload_mode="watch", "/testaudio")
test_playlist = crossfade (smart = false, fade_out=3.5, fade_in=0., duration=4., test_playlist)
test_playlist = mksafe(test_playlist)
output.icecast(%mp3(bitrate=128), ..., test_playlist)

or

test_playlist = playlist(reload_mode="watch", "/home/radio/testaudio")
def crossfade(old, new) =
cross.simple(old.source, new.source, fade_in=0.0, fade_out=3.50)
end
test_playlist = cross(minimum=0.00, duration=4.00, crossfade, test_playlist)
test_playlist = mksafe(test_playlist)
output.icecast(%mp3(bitrate=128), ..., test_playlist)

here are files: https://rock.omfm.ru/test/audio1.mp3 https://rock.omfm.ru/test/audio2.mp3 https://rock.omfm.ru/test/audio3.mp3

3 identical files. Every other time (strangely enough) you can here a click at the end of fade_out. A small one. In production environment those clicks could be much louder depending on a quality and loudness of the tracks.

toots commented 10 months ago

This is awesome thank you. I'm finishing the new streaming model for the main branch, this'll be a good opportunity to test it. I'll also look at fixing in the 2.2.x branch. I'll be back to you as soon as possible.

RM-FM commented 9 months ago

@toots Please also #3610 as it might be related to this issue.

toots commented 9 months ago

Hi @RM-FM and @gAlleb ! Are y'all able to test the latest main? The new streaming API has been merged there and I suspect this should fix this issue. We also need to have people test it in case it breaks for them. Those changes were awesome but pretty extensive!

gAlleb commented 9 months ago

Hi @toots. Have tested with the above example on Ubuntu 22.04 opam

liquidsoap  --version
Liquidsoap 2.3.0+git@482d23cfe
Copyright (c) 2003-2023 Savonet team
  1. First of all
    test_playlist = playlist(reload_mode="watch", "/home/radio/testaudio")
    def crossfade(old, new) =
    cross.simple(old.source, new.source, fade_in=0.0, fade_out=3.50)
    end
    test_playlist = cross(minimum=0.00, duration=4.00, crossfade, test_playlist)
    test_playlist = mksafe(test_playlist)
    output.icecast(%mp3(bitrate=128), ..., test_playlist)

    doesn't work because

    
    At scripts/test.liq, line 6, char 30-34:
    test_playlist = cross(minimum=0.00, duration=4.00, crossfade, test_playlist)

Error 6: Cannot apply that parameter because the function at scripts/test.liq, line 6, char 16-22 has no argument labeled "minimum"!


2.

test_playlist = playlist(reload_mode="watch", "/testaudio") test_playlist = crossfade (smart = false, fade_out=3.5, fade_in=0., duration=4., test_playlist) test_playlist = mksafe(test_playlist) output.icecast(%mp3(bitrate=128), ..., test_playlist)


Script works but the problem persists.
RM-FM commented 9 months ago

@toots I also tested today with the latest rolling Azuracast release. Both problems - metadata and clicks - persist.

gAlleb commented 9 months ago

@RM-FM Hi! Latest Azuracast RR has liquidsoap 2.2.3 so these issues couldn't have been fixed there.

@toots, just for fun I have installed 2.1.4 and tested with the above script — no pops/clicks :) 2.3.0+git@482d23cfe — the same pops/clicks as in 2.2.3, 2.2.0. Yeah, I think the latest version without "clicks" has been 2.1.4.

Tried Liquidsoap 2.3.0+git@a042e5b71 this morning to be sure. Pops/clicks persist. Plus another strange thing with latest 2.3.0+git@a042e5b71 — I've got a small jingle which plays when script starts and after it has played — the icecast title doesn't show the new changed title of the next song. Title changes only after second track (track after jingle) has played through. Couldn't find anything useful in logs about this behavior.

toots commented 9 months ago

Okay y'all, pretty sure I got it this time. Are y'all able to test with https://github.com/savonet/liquidsoap/releases/tag/rolling-release-v2.2.x ?

gAlleb commented 9 months ago

Hi @toots It's great! Thank you for your work! Have just tested with

HEAD is now at 430281174 Release build
$ liquidsoap --version
Liquidsoap rolling-release-v2.2.x-1-g4302811+dev
Copyright (c) 2003-2023 Savonet team

And couldn't hear any clicks :) Gonna listen further. Should push it to release 2.2.4 so Azuracast folks could upgrade and test as well.

Thanks again!

P.S. So what was the well hidden core of the issue?)

toots commented 9 months ago

Great, glad to know.

Yeah I'm gonna fast track this out, I'm suspecting it might impact some people.

Thanks for y'all patience!

toots commented 9 months ago

Ha I forgot: the core of the issue was a small mistake in the rewrite of the add operator with the new muxer/multi-track. When muxing several audio sources, we were picking the smallest frame size available which led to tiny fraction of the audio data (we're talking perhaps 0.01s) being lost if one source had a longer frame.

This would typically happen in crossfade transitions because we're usually adding maybe 4.00s with 3.98s. But only when doing a cross-fade (which adds fade.in/fade.out) but not when doing a sequence.

Overall, the human ear is pretty amazing and can detect the tiniest loss/discontinuity of audio data. Also, it's pretty fun to debug things by ear.

Probably less funny for people using the software, though so let's get this out!

gAlleb commented 9 months ago

Thanks again!

gAlleb commented 9 months ago

@RM-FM you can update your Azuracast installation now to test this fix since it's updated to Liquidsoap Rolling Release.

RM-FM commented 9 months ago

@toots @gAlleb It seems that the clicks are gone indeed. What a smooth listening experience! This fixes also #6749 then I guess...Thank you so much!

Unfortunately, it didn't fix the issue with the missing meta data update after unexpected track endings (would have been too good to be true): #6778 https://github.com/savonet/liquidsoap/issues/3610