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

Distorted audio at loop points in AudioFileProcessor (nightly) #7094

Closed
khoidauminh opened this issue Feb 9, 2024 · 20 comments · Fixed by #7100
Closed

Distorted audio at loop points in AudioFileProcessor (nightly) #7094

khoidauminh opened this issue Feb 9, 2024 · 20 comments · Fixed by #7100
Labels

Comments

@khoidauminh
Copy link
Contributor

Bug Summary

Audio becomes distorted when AFP reaches the loop region of sample

Steps to reproduce

  1. Download the latest nightly build of LMMS (gc2052151a as of writing this bug report)
  2. Open AFP and import a sample/waveform sample
  3. Set loop points to the sample's waveform cycle or to the whole sample
  4. Play the sample (especially at high notes)

Expected behavior

Sample is played normally

Actual behavior

Sample is played incorrectly at the loop points, resulting in distorted audio

Screenshots and audio files

image

Audio in old LMMS

afp_old_alpha.mp4

Audio in latest LMMS

afp_new_alpha.mp4
LMMS build

image

@khoidauminh khoidauminh added the bug label Feb 9, 2024
@khoidauminh
Copy link
Contributor Author

It seems like ce722dd introduced the bug

@michaelgregorius
Copy link
Contributor

It seems like ce722dd introduced the bug

@sakertooth, do you have an idea what might cause this?

I have to admin that I would never have thought about using AFP as a wavetable synthesizer but here we go. 😅

@sakertooth
Copy link
Contributor

@sakertooth, do you have an idea what might cause this?

My guess is that somethings incorrect in Sample::play, as it sounds like a resampling issue?

@sakertooth
Copy link
Contributor

Let me know if you're looking to find a solution to this @michaelgregorius.

@michaelgregorius
Copy link
Contributor

I think I'll pass on this @sakertooth. I am currently working on other things and the aforementioned commit seems to have introduced lots of changes.

@sakertooth
Copy link
Contributor

I think I'll pass on this @sakertooth. I am currently working on other things and the aforementioned commit seems to have introduced lots of changes.

No problem, I can look into this for sure. Just wanted to know so that work doesn't start to overlap. 👍

@khoidauminh
Copy link
Contributor Author

After digging into the source code, I think the error originates from Sample:play and Sample::playSampleRange:

In the Loop::On case:

case Loop::
    state->m_frameIndex = std::clamp(state->m_frameIndex, start, loopEnd);
    if (state->m_frameIndex == loopEnd) { state->m_frameIndex = loopStart; }
    break;

From my understanding, m_frameIndex is being clamped (instead of the modulo operation being applied to it) resulting in incorrect looping.

Then in Sample::playSampleRange:

void Sample::playSampleRange(PlaybackState* state, sampleFrame* dst, size_t numFrames) const
{
    auto framesToCopy = 0;
    
          /// ...
    
    if (framesToCopy < numFrames) { std::fill_n(dst + framesToCopy, numFrames - framesToCopy, sampleFrame{0, 0}); }
}

In cases where the loop region is smaller than playBuffer's size, instead of going back to loopStartFrame() and continuing to copy, the rest of the buffer is filled with zero instead.

Similar thing happens to the Loop::PingPong case.

@khoidauminh
Copy link
Contributor Author

It seems like ce722dd introduced the bug

@sakertooth, do you have an idea what might cause this?

I have to admin that I would never have thought about using AFP as a wavetable synthesizer but here we go. 😅

I think the feature is very useful on short (or bass) samples where you want a quick way to lengthen them without the artifacts of audio-stretching or clipping, which requires the loop points to precisely match the waveform cycle. I use it a lot

@sakertooth
Copy link
Contributor

Thanks for the lead @khoidauminh, I was thinking the calculation of resampleRatio was wrong somehow and causing a resampling issue. I'm now looking into changing the code to use a modulus again when looping. playSampleRange should still be able to be used for both looping and ping pong, but I suppose the code should be calling it multiple times as necessary within a while loop.

@sakertooth
Copy link
Contributor

Hey @khoidauminh, so I believe I fixed this issue in #7100 just from listening to the playback I got, but could you check on your end to be sure?

@khoidauminh
Copy link
Contributor Author

khoidauminh commented Feb 12, 2024

@sakertooth I've tested the fix and can confirm it's fixing the problem. However, I'm receiving some new problems.

  1. I'm receiving much more frequent crashes when opening a new project (or another existing project) while the song (or one or more notes) is still playing. Under Debug mode (gdb) this yields:
Thread 1 "lmms" received signal SIGSEGV, Segmentation fault.
0x00007ffff655c16d in ?? () from /usr/lib/libQt5Core.so.5
  1. Sample tracks play at the beginning regardless of where I'm at in the song

At first I suspected the crash occurs on projects with the AFP but I noticed it's happening on other projects as well, and the crash is consistent. I suggest testing this on your end as well.

I'm also gonna look into the code for both issues and hopefully find the source of the bugs to help speed up the process

@sakertooth
Copy link
Contributor

I'm receiving much more frequent crashes when opening a new project (or another existing project) while the song (or one or more notes) is still playing. Under Debug mode this yields:

Could you send the full backtrace for this?

@khoidauminh
Copy link
Contributor Author

@sakertooth
Here's what was shown in gdb
log.txt

@sakertooth
Copy link
Contributor

Sorry, but I mean what do you get as output after entering in bt to GDB?

@khoidauminh
Copy link
Contributor Author

I also looked at journalctl -f and this is what I found

Thg 2 12 22:38:23 kpc lmms-alpha.desktop[238994]: fluidsynth: warning: No preset found on channel 10 [bank=0 prog=0]
Thg 2 12 22:38:23 kpc lmms-alpha.desktop[238994]: fluidsynth: warning: No preset found on channel 11 [bank=0 prog=0]
Thg 2 12 22:38:23 kpc lmms-alpha.desktop[238994]: fluidsynth: warning: No preset found on channel 12 [bank=0 prog=0]
Thg 2 12 22:38:23 kpc lmms-alpha.desktop[238994]: fluidsynth: warning: No preset found on channel 13 [bank=0 prog=0]
Thg 2 12 22:38:23 kpc lmms-alpha.desktop[238994]: fluidsynth: warning: No preset found on channel 14 [bank=0 prog=0]
Thg 2 12 22:38:23 kpc lmms-alpha.desktop[238994]: fluidsynth: warning: No preset found on channel 15 [bank=0 prog=0]
Thg 2 12 22:38:23 kpc kernel: lmms[238994]: segfault at 1e10000021c ip 000076909135c16d sp 00007fffa2a1e6f0 error 4 in libQt5Core.so.5.15.12[76909109f000+2dd000] likely on CPU 10 (core 2, socket 0)
Thg 2 12 22:38:23 kpc kernel: Code: 59 ac 1d 00 48 c1 ea 04 48 69 d2 18 04 00 00 48 29 d1 48 83 e1 f8 4d 8d 3c 0e 48 89 4d 80 4c 89 ff e8 67 09 d8 ff 48 8b 43 08 <4c> 8b 68 40 4d 85 ed 0f 84 16 01 00 00 4c 89 6d b0 f0 41 83 45 04
Thg 2 12 22:38:23 kpc systemd[1]: Started Process Core Dump (PID 239147/UID 0).
Thg 2 12 22:38:25 kpc systemd-coredump[239150]: [🡕] Process 238994 (lmms) of user 1000 dumped core.
                                                
                                                Stack trace of thread 238994:
                                                #0  0x000076909135c16d n/a (libQt5Core.so.5 + 0x35c16d)
                                                #1  0x00007690912cade6 _ZN7QObject14disconnectImplEPKS_PPvS1_S3_PK11QMetaObject (libQt5Core.so.5 + 0x2cade6)
                                                #2  0x0000578fa5335051 n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x406051)
                                                #3  0x0000578fa533335a n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x40435a)
                                                #4  0x0000578fa5332aab n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x403aab)
                                                #5  0x0000578fa5334198 n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x405198)
                                                #6  0x0000578fa527decf n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x34eecf)
                                                #7  0x0000578fa527e8f9 n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x34f8f9)
                                                #8  0x0000578fa527e561 n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x34f561)
                                                #9  0x0000578fa527e134 n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x34f134)
                                                #10 0x0000578fa53197d4 n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x3ea7d4)
                                                #11 0x0000578fa5198496 n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x269496)
                                                #12 0x00007690912d0fe3 n/a (libQt5Core.so.5 + 0x2d0fe3)
                                                #13 0x000076909285c727 _ZN15QAbstractButton7clickedEb (libQt5Widgets.so.5 + 0x25c727)
                                                #14 0x000076909285efda n/a (libQt5Widgets.so.5 + 0x25efda)
                                                #15 0x00007690928604dc n/a (libQt5Widgets.so.5 + 0x2604dc)
                                                #16 0x0000769092860680 _ZN15QAbstractButton17mouseReleaseEventEP11QMouseEvent (libQt5Widgets.so.5 + 0x260680)
                                                #17 0x000076909295380f _ZN11QToolButton17mouseReleaseEventEP11QMouseEvent (libQt5Widgets.so.5 + 0x35380f)
                                                #18 0x00007690927af1a1 _ZN7QWidget5eventEP6QEvent (libQt5Widgets.so.5 + 0x1af1a1)
                                                #19 0x00007690927788ff _ZN19QApplicationPrivate13notify_helperEP7QObjectP6QEvent (libQt5Widgets.so.5 + 0x1788ff)
                                                #20 0x000076909277ddaf _ZN12QApplication6notifyEP7QObjectP6QEvent (libQt5Widgets.so.5 + 0x17ddaf)
                                                #21 0x000076909129bef8 _ZN16QCoreApplication15notifyInternal2EP7QObjectP6QEvent (libQt5Core.so.5 + 0x29bef8)
                                                #22 0x000076909277c0ea _ZN19QApplicationPrivate14sendMouseEventEP7QWidgetP11QMouseEventS1_S1_PS1_R8QPointerIS0_Ebb (libQt5Widgets.so.5 + 0x17c0ea)
                                                #23 0x00007690927ccec5 n/a (libQt5Widgets.so.5 + 0x1ccec5)
                                                #24 0x00007690927cec17 n/a (libQt5Widgets.so.5 + 0x1cec17)
                                                #25 0x00007690927788ff _ZN19QApplicationPrivate13notify_helperEP7QObjectP6QEvent (libQt5Widgets.so.5 + 0x1788ff)
                                                #26 0x000076909129bef8 _ZN16QCoreApplication15notifyInternal2EP7QObjectP6QEvent (libQt5Core.so.5 + 0x29bef8)
                                                #27 0x000076909174196c _ZN22QGuiApplicationPrivate17processMouseEventEPN29QWindowSystemInterfacePrivate10MouseEventE (libQt5Gui.so.5 + 0x14196c)
                                                #28 0x000076909172a6f5 _ZN22QWindowSystemInterface22sendWindowSystemEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEE (libQt5Gui.so.5 + 0x12a6f5)
                                                #29 0x000076908d6a8540 n/a (libQt5XcbQpa.so.5 + 0x65540)
                                                #30 0x000076908fd0df69 n/a (libglib-2.0.so.0 + 0x59f69)
                                                #31 0x000076908fd6c3a7 n/a (libglib-2.0.so.0 + 0xb83a7)
                                                #32 0x000076908fd0c162 g_main_context_iteration (libglib-2.0.so.0 + 0x58162)
                                                #33 0x00007690912ead0c _ZN20QEventDispatcherGlib13processEventsE6QFlagsIN10QEventLoop17ProcessEventsFlagEE (libQt5Core.so.5 + 0x2ead0c)
                                                #34 0x000076909129ac04 _ZN10QEventLoop4execE6QFlagsINS_17ProcessEventsFlagEE (libQt5Core.so.5 + 0x29ac04)
                                                #35 0x000076909129c0a3 _ZN16QCoreApplication4execEv (libQt5Core.so.5 + 0x29c0a3)
                                                #36 0x0000578fa5188e4c n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x259e4c)
                                                #37 0x0000769090a43cd0 n/a (libc.so.6 + 0x25cd0)
                                                #38 0x0000769090a43d8a __libc_start_main (libc.so.6 + 0x25d8a)
                                                #39 0x0000578fa5184ea5 n/a (/kdm/home/kdm/git/lmms/build/lmms + 0x255ea5)
                                                ELF object binary architecture: AMD x86-64
Thg 2 12 22:38:25 kpc systemd[1]: [email protected]: Deactivated successfully.
Thg 2 12 22:38:25 kpc systemd[11004]: app-gnome-lmms\x2dalpha-238994.scope: Consumed 9.732s CPU time.
Thg 2 12 22:38:25 kpc systemd[1]: [email protected]: Consumed 1.172s CPU time.


@khoidauminh
Copy link
Contributor Author

Sorry, but I mean what do you get as output after entering in bt to GDB?

@sakertooth

(gdb) bt
#0  0x00007ffff655c16d in ??? () at /usr/lib/libQt5Core.so.5
#1  0x00007ffff64cade6 in QObject::disconnectImpl(QObject const*, void**, QObject const*, void**, QMetaObject const*) () at /usr/lib/libQt5Core.so.5
#2  0x000055555595a051 in QObject::disconnect<void (lmms::Model::*)(), void (lmms::gui::MixerView::*)()>
    (sender=0x55555671d710, signal=(void (lmms::Model::*)(lmms::Model * const)) 0x5555557c06de <lmms::Model::dataChanged()>, receiver=0x55555ce96840, slot=(void (lmms::gui::MixerView::*)(lmms::gui::MixerView * const)) 0x555555958114 <lmms::gui::MixerView::toggledMute()>) at /usr/include/qt/QtCore/qobject.h:380
#3  0x000055555595835a in lmms::gui::MixerView::disconnectFromSoloAndMute (this=0x55555ce96840, channelIndex=1) at /home/kdm/git/lmms/src/gui/MixerView.cpp:327
#4  0x0000555555957aab in lmms::gui::MixerView::refreshDisplay (this=0x55555ce96840) at /home/kdm/git/lmms/src/gui/MixerView.cpp:211
#5  0x0000555555959198 in lmms::gui::MixerView::clear (this=0x55555ce96840) at /home/kdm/git/lmms/src/gui/MixerView.cpp:595
#6  0x00005555558a2ecf in lmms::Song::clearProject (this=0x555556cf9260) at /home/kdm/git/lmms/src/core/Song.cpp:866
#7  0x00005555558a38f9 in lmms::Song::loadProject (this=0x555556cf9260, fileName=...) at /home/kdm/git/lmms/src/core/Song.cpp:1057
#8  0x00005555558a3561 in lmms::Song::createNewProjectFromTemplate (this=0x555556cf9260, templ=...) at /home/kdm/git/lmms/src/core/Song.cpp:983
#9  0x00005555558a3134 in lmms::Song::createNewProject (this=0x555556cf9260) at /home/kdm/git/lmms/src/core/Song.cpp:927
#10 0x000055555593e7d4 in lmms::gui::MainWindow::createNewProject (this=0x555556ce6d90) at /home/kdm/git/lmms/src/gui/MainWindow.cpp:754
#11 0x00005555557bd496 in lmms::gui::MainWindow::qt_static_metacall (_o=0x555556ce6d90, _c=QMetaObject::InvokeMetaMethod, _id=4, _a=0x7fffffffd5f0) at /home/kdm/git/lmms/build/src/lmmsobjs_autogen/DGKZTCOIDE/moc_MainWindow.cpp:217
#12 0x00007ffff64d0fe3 in ??? () at /usr/lib/libQt5Core.so.5
#13 0x00007ffff7a5c727 in QAbstractButton::clicked(bool) () at /usr/lib/libQt5Widgets.so.5
#14 0x00007ffff7a5efda in ??? () at /usr/lib/libQt5Widgets.so.5
#15 0x00007ffff7a604dc in ??? () at /usr/lib/libQt5Widgets.so.5
#16 0x00007ffff7a60680 in QAbstractButton::mouseReleaseEvent(QMouseEvent*) () at /usr/lib/libQt5Widgets.so.5
#17 0x00007ffff7b5380f in QToolButton::mouseReleaseEvent(QMouseEvent*) () at /usr/lib/libQt5Widgets.so.5
#18 0x00007ffff79af1a1 in QWidget::event(QEvent*) () at /usr/lib/libQt5Widgets.so.5
#19 0x00007ffff79788ff in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /usr/lib/libQt5Widgets.so.5
#20 0x00007ffff797ddaf in QApplication::notify(QObject*, QEvent*) () at /usr/lib/libQt5Widgets.so.5
#21 0x00007ffff649bef8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /usr/lib/libQt5Core.so.5
#22 0x00007ffff797c0ea in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool, bool) () at /usr/lib/libQt5Widgets.so.5
#23 0x00007ffff79ccec5 in ??? () at /usr/lib/libQt5Widgets.so.5
#24 0x00007ffff79cec17 in ??? () at /usr/lib/libQt5Widgets.so.5
#25 0x00007ffff79788ff in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /usr/lib/libQt5Widgets.so.5
#26 0x00007ffff649bef8 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /usr/lib/libQt5Core.so.5
#27 0x00007ffff694196c in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) () at /usr/lib/libQt5Gui.so.5
#28 0x00007ffff692a6f5 in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Gui.so.5
#29 0x00007ffff292bcf5 in ??? () at /usr/lib/libQt5WaylandClient.so.5
#30 0x00007ffff4f0df69 in ??? () at /usr/lib/libglib-2.0.so.0
#31 0x00007ffff4f6c3a7 in ??? () at /usr/lib/libglib-2.0.so.0
#32 0x00007ffff4f0c162 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#33 0x00007ffff64ead0c in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#34 0x00007ffff649ac04 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#35 0x00007ffff649c0a3 in QCoreApplication::exec() () at /usr/lib/libQt5Core.so.5
#36 0x00005555557ade4c in main (argc=1, argv=0x7fffffffe628) at /home/kdm/git/lmms/src/core/main.cpp:1018

@sakertooth
Copy link
Contributor

This should've been fixed after #7081.

@khoidauminh
Copy link
Contributor Author

@sakertooth I'm assuming the #7100 happened before #7081 was merged so my git fetch didn't get that. I tried both and am indeed no longer getting crashes. Sorry for the noise

The final problem left now is the Sample track playback issue

@sakertooth
Copy link
Contributor

The final problem left now is the Sample track playback issue

Did some thinking, and I am pretty sure I know why this issue happens. Will try and patch it after work.

@khoidauminh
Copy link
Contributor Author

I've been testing the new commits and am happy to say that everything is great!
Thank you very much for the work @sakertooth ! Hope the pull request gets merged soon.
Marking this issue as completed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants