jarikomppa / soloud

Free, easy, portable audio engine for games
http://soloud-audio.com
Other
1.69k stars 270 forks source link

stop and play behavior on a queue #291

Open TwoDimensionsReturn opened 3 years ago

TwoDimensionsReturn commented 3 years ago

Expected behavior:

Stop on a queue should always stop the playing

Actual behavior:

When I play a queue loaded with sounds, it plays as expected. When I stop it, it stops playing. When I play it again, it does play. But when I try to stop it again, it is ignored.

Steps to reproduce the problem:

`

SoLoud::Soloud soloud; // Engine core
SoLoud::Queue queue; // One queue

soloud.init();

// Load sample
SoLoud::Wav wav1;
wav1.load("t11_lapin_intro_1.mp3");
SoLoud::Wav wav2;
wav2.load("t11_lapin_verse_1.mp3");

soloud.play(queue); // Play the queue

queue.play(wav1);             // Play it
queue.play(wav2);

soloud.stop(queue.mQueueHandle);
    soloud.play(queue);
    soloud.stop(queue.mQueueHandle);

// Wait for voice to finish
while (true)
{
    // Still going, sleep for a bit
    SoLoud::Thread::sleep(100);
}

// Clean up SoLoud
soloud.deinit();

// All done.
return 0;

`

SoLoud version, operating system, backend used, any other potentially useful information:

RELEASE_20200207 Windows 10 SDL 2 C++ context with Visual Studio Community 17

klein-j commented 3 months ago

I can confirm it. Queue seems to be "single use only". Other occurrences of the same problem:

Once the queue stops playing for one reason or another, it does not work anymore. Something must get deleted and never recreated. The problem is hard to see at first glance, maybe it has something to do with the queue being also single-instance-only.

klein-j commented 3 months ago

I identified a number of issues so far.

Firstly, counter intuitively, you can have an empty queue that is in play state (through calling SoLoud::play(queue)). Then, if you queue songs via the queue::play function, they will play. If the queue reaches its end, it will stop playing. Passing more sounds via queue::play does nothing, as the underlying sound inside SoLoud is still in the "not playing" state, since it finished somewhen.

The QueueInstance has a hasEnded() function that can be used to determine, if SoLoud::play(queue) should be called again. Alas, if the queue stopped playing because it reached its end, so underlying SoLound framework will delete the Instance object, the queue object is then left with an invalid pointer, you can neither check if the instance hasEnded, nor is there a way to check if the instance still exists or if it should be recreated.

With some hacks, these notifications can be implemented, so finally I can check if the instance exists and if it has ended and restart the queue.

However, there is also no function to delete or pop sounds from the queue, which you often may want to do. For instance, I tried to write a proper Queue::stop() function, which empties the queue so that you can start again with a fresh one (there should also be a function to just pause it, without deleting its content, but I haven't looked into this). However, implementing this is tricky, since the stop() function from the base class is not virtual and thus cannot be overloaded. For now I simply have a stop_queue() function, which is ugly as the user has to call the correct function and is in trouble when calling the wrong one.

There is also a findQueueHandle() function with some associated variables that is called regularly but has no effect. It is confusing and I have no idea why it exists.

So far, almost everything about the Queue class is a complete mess. Most things work for me now but I have no idea if there are memory leaks, I discovered problems with the original self-written memory management in the past and judging by the code have little confidence that it works correctly here, but eh, one problem at a time.

I will debug more and eventually upload my changes.

klein-j commented 3 months ago

I implemented everything and have tried it out for a while, for now it works fine for me. You can find everything here:

https://github.com/klein-j/soloud_fixed/tree/soloud_fixed