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>
This commit is contained in:
Crystalwarrior 2022-07-27 01:27:01 +03:00 committed by GitHub
parent f8c2b1a2f0
commit b9e9e02977
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 25 deletions

View File

@ -19,14 +19,21 @@ public:
AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app); AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app);
virtual ~AOMusicPlayer(); virtual ~AOMusicPlayer();
void set_volume(int p_value, int channel = -1); 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); void set_muted(bool toggle);
const int m_channelmax = 4; const int m_channelmax = 4;
// These have to be public for the stupid sync thing // 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<QString> music_watcher; QFutureWatcher<QString> music_watcher;

View File

@ -56,7 +56,7 @@ QString AOMusicPlayer::play(QString p_song, int channel, bool loop,
QString d_path = f_path + ".txt"; QString d_path = f_path + ".txt";
loop_start[channel] = 0; 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 if (loop && file_exists(d_path)) // Contains loop/etc. information file
{ {
QStringList lines = ao_app->read_file(d_path).split("\n"); 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; int num_channels = 2;
// Calculate the bytes for loop_start/loop_end to use with the sync proc // Calculate the bytes for loop_start/loop_end to use with the sync proc
QWORD bytes = static_cast<QWORD>(args[1].trimmed().toFloat() * QWORD bytes = static_cast<QWORD>(args[1].trimmed().toUInt() *
sample_size * num_channels); sample_size * num_channels);
if (arg == "loop_start") if (arg == "loop_start")
loop_start[channel] = bytes; 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" qDebug() << "Found data file for song" << p_song << "length"
<< BASS_ChannelGetLength(newstream, BASS_POS_BYTE) << "loop start" << 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) { 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); 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 (!loop_song) {
if (!m_looping) {
if (BASS_ChannelFlags(m_stream_list[channel], 0, 0) & BASS_SAMPLE_LOOP) if (BASS_ChannelFlags(m_stream_list[channel], 0, 0) & BASS_SAMPLE_LOOP)
BASS_ChannelFlags(m_stream_list[channel], 0, BASS_ChannelFlags(m_stream_list[channel], 0,
BASS_SAMPLE_LOOP); // remove the LOOP flag BASS_SAMPLE_LOOP); // remove the LOOP flag
BASS_ChannelRemoveSync(m_stream_list[channel], loop_sync[channel]); BASS_ChannelRemoveSync(m_stream_list[channel], loop_sync[channel]);
loop_sync[channel] = 0; loop_sync[channel] = 0;
return;
} }
else {
BASS_ChannelFlags(m_stream_list[channel], BASS_SAMPLE_LOOP, BASS_ChannelFlags(m_stream_list[channel], BASS_SAMPLE_LOOP,
BASS_SAMPLE_LOOP); // set the LOOP flag BASS_SAMPLE_LOOP); // set the LOOP flag
if (loop_sync[channel] != 0) { if (loop_sync[channel] != 0) {
BASS_ChannelRemoveSync(m_stream_list[channel], BASS_ChannelRemoveSync(m_stream_list[channel],
loop_sync[channel]); // remove the sync loop_sync[channel]); // remove the sync
loop_sync[channel] = 0; 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) { else
if (loop_end[channel] == 0) {
loop_end[channel] = //Loop when the end of the file is reached.
BASS_ChannelGetLength(m_stream_list[channel], BASS_POS_BYTE); loop_sync[channel] = BASS_ChannelSetSync(
if (loop_end[channel] > m_stream_list[channel], BASS_SYNC_POS | BASS_SYNC_MIXTIME,
0) // Don't loop zero length songs even if we're asked to 0 , loopProc, &loop_start[channel]);
loop_sync[channel] = BASS_ChannelSetSync(
m_stream_list[channel], BASS_SYNC_POS | BASS_SYNC_MIXTIME,
loop_end[channel], loopProc, &loop_start[channel]);
} }
} }
} }