Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EngineBuffer: Fix assert when new track is loaded during playback with sync #4682

Merged

Conversation

Holzhaus
Copy link
Member

When loading a track that is not yet present in the library (and thus
doesn't have any BPM because it hasn't been analyzed yet) while another
deck is playing and both decks have sync enabled, a debug assertion is
triggered:

DEBUG ASSERT: "isValid()" in function double mixxx::Bpm::value() const at src/track/bpm.h:53
Aborted (core dumped)

The backtrace looks as follows:

#0  0x00007f175c87234c in __pthread_kill_implementation () at /usr/lib/libc.so.6
#1  0x00007f175c8254b8 in raise () at /usr/lib/libc.so.6
#2  0x00007f175c80f534 in abort () at /usr/lib/libc.so.6
#3  0x00007f175cf05ee4 in qt_assert(char const*, char const*, int) () at /usr/lib/libQt5Core.so.5
#4  0x000055deb2e67e1c in mixxx::(anonymous namespace)::handleMessage(QtMsgType, QMessageLogContext const&, QString const&) (type=<optimized out>, context=<optimized out>, input=<optimized out>) at src/util/logging.cpp:355
#5  0x00007f175cf47128 in  () at /usr/lib/libQt5Core.so.5
#6  0x00007f175cf3fd8a in  () at /usr/lib/libQt5Core.so.5
#7  0x00007f175cf06526 in QMessageLogger::critical(char const*, ...) const () at /usr/lib/libQt5Core.so.5
#8  0x000055deb2e5c720 in mixxx_debug_assert(char const*, char const*, int, char const*) (assertion=assertion@entry=0x55deb39bd0db "isValid()", file=file@entry=0x55deb39bbf30 "src/track/bpm.h", line=line@entry=53, function=function@entry=0x55deb39bbf08 "double mixxx::Bpm::value() const") at gsrc/util/assert.h:9
#9  0x000055deb2ee7e7e in mixxx_debug_assert_return_true(char const*, char const*, int, char const*) (function=0x55deb39bbf08 "double mixxx::Bpm::value() const", line=53, file=0x55deb39bbf30 "src/track/bpm.h", assertion=0x55deb39bd0db "isValid()") at gsrc/util/assert.h:18
#10 mixxx::Bpm::value() const (this=<synthetic pointer>) at src/track/bpm.h:53
#11 mixxx::operator*(mixxx::Bpm, double) (multiple=1, bpm=...) at src/track/bpm.h:160
#12 SyncControl::setLocalBpm(mixxx::Bpm) (this=<optimized out>, localBpm=...) at src/engine/sync/synccontrol.cpp:567
#13 0x000055deb34c7ba3 in EngineBuffer::postProcess(int) (this=0x55deb56eb060, iBufferSize=2048) at src/engine/enginebuffer.cpp:1318
#14 0x000055deb3139023 in EngineMaster::processChannels(int) (this=0x55deb5449440, iBufferSize=<optimized out>) at src/engine/enginemaster.cpp:383
#15 0x000055deb31394f7 in EngineMaster::process(int) (this=0x55deb5449440, iBufferSize=iBufferSize@entry=2048) at src/engine/enginemaster.cpp:410
#16 0x000055deb2f91d0b in SoundManager::onDeviceOutputCallback(long) (this=<optimized out>, iFramesPerBuffer=iFramesPerBuffer@entry=1024) at src/soundio/soundmanager.cpp:596
#17 0x000055deb32dd794 in SoundDevicePortAudio::callbackProcessClkRef(long, float*, float const*, PaStreamCallbackTimeInfo const*, unsigned long) (this=0x55deb553e6b0, framesPerBuffer=1024, out=<optimized out>, in=<optimized out>, timeInfo=<optimized out>, statusFlags=<optimized out>) at src/soundio/sounddeviceportaudio.cpp:965

This happens because newLocalBpm is invalid when localBpm is
invalid. Trying to do sync decks while no tempo information is available
does not make sense, so we only synchronize decks if the local BPM is
available.

@Holzhaus Holzhaus added this to the 2.4.0 milestone Feb 21, 2022
Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, Thank you.
@ywwg, do you also want to have a look?

@ronso0
Copy link
Member

ronso0 commented Feb 22, 2022

I'm curious: what's the UX in this case? is Sync disabled?
is the new track synced after analysis has finished and the track isn't playing yet?

@ywwg
Copy link
Member

ywwg commented Feb 25, 2022

yes I'd like to know what happens when there is no bpm available, and then the bpm appears -- I think Sync Lock will do the right thing.

@ywwg
Copy link
Member

ywwg commented Feb 25, 2022

yes I'd like to know what happens when there is no bpm available, and then the bpm appears -- I think Sync Lock will do the right thing.

@daschuer
Copy link
Member

@ywwg can we merge this?

…h sync

When loading a track that is not yet present in the library (and thus
doesn't have any BPM because it hasn't been analyzed yet) while another
deck is playing and both decks have sync enabled, a debug assertion is
triggered:

    DEBUG ASSERT: "isValid()" in function double mixxx::Bpm::value() const at src/track/bpm.h:53
    Aborted (core dumped)

The backtrace looks as follows:

    #0  0x00007f175c87234c in __pthread_kill_implementation () at /usr/lib/libc.so.6
    #1  0x00007f175c8254b8 in raise () at /usr/lib/libc.so.6
    #2  0x00007f175c80f534 in abort () at /usr/lib/libc.so.6
    #3  0x00007f175cf05ee4 in qt_assert(char const*, char const*, int) () at /usr/lib/libQt5Core.so.5
    #4  0x000055deb2e67e1c in mixxx::(anonymous namespace)::handleMessage(QtMsgType, QMessageLogContext const&, QString const&) (type=<optimized out>, context=<optimized out>, input=<optimized out>) at src/util/logging.cpp:355
    #5  0x00007f175cf47128 in  () at /usr/lib/libQt5Core.so.5
    #6  0x00007f175cf3fd8a in  () at /usr/lib/libQt5Core.so.5
    #7  0x00007f175cf06526 in QMessageLogger::critical(char const*, ...) const () at /usr/lib/libQt5Core.so.5
    #8  0x000055deb2e5c720 in mixxx_debug_assert(char const*, char const*, int, char const*) (assertion=assertion@entry=0x55deb39bd0db "isValid()", file=file@entry=0x55deb39bbf30 "src/track/bpm.h", line=line@entry=53, function=function@entry=0x55deb39bbf08 "double mixxx::Bpm::value() const") at gsrc/util/assert.h:9
    #9  0x000055deb2ee7e7e in mixxx_debug_assert_return_true(char const*, char const*, int, char const*) (function=0x55deb39bbf08 "double mixxx::Bpm::value() const", line=53, file=0x55deb39bbf30 "src/track/bpm.h", assertion=0x55deb39bd0db "isValid()") at gsrc/util/assert.h:18
    #10 mixxx::Bpm::value() const (this=<synthetic pointer>) at src/track/bpm.h:53
    #11 mixxx::operator*(mixxx::Bpm, double) (multiple=1, bpm=...) at src/track/bpm.h:160
    #12 SyncControl::setLocalBpm(mixxx::Bpm) (this=<optimized out>, localBpm=...) at src/engine/sync/synccontrol.cpp:567
    #13 0x000055deb34c7ba3 in EngineBuffer::postProcess(int) (this=0x55deb56eb060, iBufferSize=2048) at src/engine/enginebuffer.cpp:1318
    #14 0x000055deb3139023 in EngineMaster::processChannels(int) (this=0x55deb5449440, iBufferSize=<optimized out>) at src/engine/enginemaster.cpp:383
    #15 0x000055deb31394f7 in EngineMaster::process(int) (this=0x55deb5449440, iBufferSize=iBufferSize@entry=2048) at src/engine/enginemaster.cpp:410
    #16 0x000055deb2f91d0b in SoundManager::onDeviceOutputCallback(long) (this=<optimized out>, iFramesPerBuffer=iFramesPerBuffer@entry=1024) at src/soundio/soundmanager.cpp:596
    #17 0x000055deb32dd794 in SoundDevicePortAudio::callbackProcessClkRef(long, float*, float const*, PaStreamCallbackTimeInfo const*, unsigned long) (this=0x55deb553e6b0, framesPerBuffer=1024, out=<optimized out>, in=<optimized out>, timeInfo=<optimized out>, statusFlags=<optimized out>) at src/soundio/sounddeviceportaudio.cpp:965

This happens because `newLocalBpm` is invalid when `localBpm` is
invalid. Trying to do sync decks while no tempo information is available
does not make sense, so we only synchronize decks if the local BPM is
available.
@Holzhaus Holzhaus force-pushed the enginebuffer-setlocalbpm-debug-assert-fix branch from 3565e26 to 9614a8f Compare March 1, 2022 23:12
@Holzhaus
Copy link
Member Author

Holzhaus commented Mar 1, 2022

yes I'd like to know what happens when there is no bpm available, and then the bpm appears -- I think Sync Lock will do the right thing.

Yes. But in theory I think there could theoretically be a tempo jump on the other deck once the BPM becomes available. I updated the PR to include your suggestion and now the deck becomes follower if it is soft leader and doesn't have BPM. The explicit leader property sticks, implicit leader doesn't.

Copy link
Member

@ywwg ywwg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good to merge -- I will check some edge cases and write a followup if needed

@ywwg ywwg merged commit 74ec345 into mixxxdj:main Mar 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

4 participants