From b9e9e029778e3feb63bfab47157e46496cbcbafa Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Wed, 27 Jul 2022 01:27:01 +0300 Subject: [PATCH] Fix an extremely rare issue where loop point goes outside track bounds if loop end is not defined (#748) * Fix an incredibly edge-case loop end issue where the loop end is outside track boundaries somehow * WIP-AB Cleanup and incorrect loop bugfix Cleanup AB-Loop code * Someone has to check if AB loop works properly still cause I have no idea how this shit works and the code prior was unreadable. Don't blame me, blame whoever left this code undocumented like the hag they are. * Increase max-sample we can accept in the AB loop Also change conversion to UInt. If someone adds a bad value, it will just return 0, which I guess is fair. Co-authored-by: Salanto <62221668+Salanto@users.noreply.github.com> --- include/aomusicplayer.h | 13 ++++++++--- src/aomusicplayer.cpp | 50 +++++++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/include/aomusicplayer.h b/include/aomusicplayer.h index 037525f..35bd784 100644 --- a/include/aomusicplayer.h +++ b/include/aomusicplayer.h @@ -19,14 +19,21 @@ public: AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app); virtual ~AOMusicPlayer(); void set_volume(int p_value, int channel = -1); - void set_looping(bool toggle, int channel = 0); + void set_looping(bool loop_song, int channel = 0); void set_muted(bool toggle); const int m_channelmax = 4; // These have to be public for the stupid sync thing - int loop_start[4] = {0, 0, 0, 0}; - int loop_end[4] = {0, 0, 0, 0}; + /** + * @brief The starting sample of the AB-Loop. + */ + unsigned int loop_start[4] = {0, 0, 0, 0}; + + /** + * @brief The end sample of the AB-Loop. + */ + unsigned int loop_end[4] = {0, 0, 0, 0}; QFutureWatcher music_watcher; diff --git a/src/aomusicplayer.cpp b/src/aomusicplayer.cpp index 59cf4d2..2cac91d 100644 --- a/src/aomusicplayer.cpp +++ b/src/aomusicplayer.cpp @@ -56,7 +56,7 @@ QString AOMusicPlayer::play(QString p_song, int channel, bool loop, QString d_path = f_path + ".txt"; loop_start[channel] = 0; - loop_end[channel] = BASS_ChannelGetLength(newstream, BASS_POS_BYTE); + loop_end[channel] = 0; if (loop && file_exists(d_path)) // Contains loop/etc. information file { QStringList lines = ao_app->read_file(d_path).split("\n"); @@ -76,7 +76,7 @@ QString AOMusicPlayer::play(QString p_song, int channel, bool loop, int num_channels = 2; // Calculate the bytes for loop_start/loop_end to use with the sync proc - QWORD bytes = static_cast(args[1].trimmed().toFloat() * + QWORD bytes = static_cast(args[1].trimmed().toUInt() * sample_size * num_channels); if (arg == "loop_start") loop_start[channel] = bytes; @@ -87,7 +87,7 @@ QString AOMusicPlayer::play(QString p_song, int channel, bool loop, } qDebug() << "Found data file for song" << p_song << "length" << BASS_ChannelGetLength(newstream, BASS_POS_BYTE) << "loop start" - << loop_start << "loop end" << loop_end; + << loop_start[channel] << "loop end" << loop_end[channel]; } if (BASS_ChannelIsActive(m_stream_list[channel]) == BASS_ACTIVE_PLAYING) { @@ -194,33 +194,39 @@ void CALLBACK loopProc(HSYNC handle, DWORD channel, DWORD data, void *user) BASS_ChannelLock(channel, false); } -void AOMusicPlayer::set_looping(bool toggle, int channel) +void AOMusicPlayer::set_looping(bool loop_song, int channel) { - m_looping = toggle; - if (!m_looping) { + if (!loop_song) { if (BASS_ChannelFlags(m_stream_list[channel], 0, 0) & BASS_SAMPLE_LOOP) BASS_ChannelFlags(m_stream_list[channel], 0, BASS_SAMPLE_LOOP); // remove the LOOP flag BASS_ChannelRemoveSync(m_stream_list[channel], loop_sync[channel]); loop_sync[channel] = 0; + return; } - else { - BASS_ChannelFlags(m_stream_list[channel], BASS_SAMPLE_LOOP, - BASS_SAMPLE_LOOP); // set the LOOP flag - if (loop_sync[channel] != 0) { - BASS_ChannelRemoveSync(m_stream_list[channel], - loop_sync[channel]); // remove the sync - loop_sync[channel] = 0; + + BASS_ChannelFlags(m_stream_list[channel], BASS_SAMPLE_LOOP, + BASS_SAMPLE_LOOP); // set the LOOP flag + if (loop_sync[channel] != 0) { + BASS_ChannelRemoveSync(m_stream_list[channel], + loop_sync[channel]); // remove the sync + loop_sync[channel] = 0; + } + + if (loop_start[channel] > 0) { + if (loop_end[channel] > 0 && (loop_end[channel] > loop_start[channel])) + { + //Loop when the endpoint is reached. + loop_sync[channel] = BASS_ChannelSetSync( + m_stream_list[channel], BASS_SYNC_END | BASS_SYNC_MIXTIME, + loop_end[channel] , loopProc, &loop_start[channel]); } - if (loop_start[channel] > 0) { - if (loop_end[channel] == 0) - loop_end[channel] = - BASS_ChannelGetLength(m_stream_list[channel], BASS_POS_BYTE); - if (loop_end[channel] > - 0) // Don't loop zero length songs even if we're asked to - loop_sync[channel] = BASS_ChannelSetSync( - m_stream_list[channel], BASS_SYNC_POS | BASS_SYNC_MIXTIME, - loop_end[channel], loopProc, &loop_start[channel]); + else + { + //Loop when the end of the file is reached. + loop_sync[channel] = BASS_ChannelSetSync( + m_stream_list[channel], BASS_SYNC_POS | BASS_SYNC_MIXTIME, + 0 , loopProc, &loop_start[channel]); } } }