defun-games / claylib

A Common Lisp 2D/3D game toolkit built on top of Raylib 4.5.
zlib License
69 stars 4 forks source link

Audio examples #59

Closed mjkalyan closed 1 year ago

mjkalyan commented 1 year ago

Draft PR to investigate the freezing on quit after either audio example has been run once already.

Also for any other general discussion as to how I've dealt with audio so far. There are some kinks such as not having a good place to access music assets via scenes (they may be a good candidate for scene parameters).

shelvick commented 1 year ago

Oooh, you're also going to want default-unload methods for unload-sound, unload-music-stream, etc. I don't know that is the cause of the current problem but it won't hurt.

mjkalyan commented 1 year ago

When do these default-unload methods get called? I don't see a generic default-unload in use anywhere yet. But unloading seems likely to be the fix - maybe it crashes when closing the audio device before unloading the sounds or something like that. I had done unloading in the old free method but have since removed it (as you noted I also forgot the music asset and list free, but have since removed those too).

shelvick commented 1 year ago

Sorry, not methods. They're macros, similar to the old default-free. They just override the default finalizer for certain types and make sure a unload-* function is called.

Example usage: (default-unload claylib/ll:model unload-model t). Last parameter should be T if a window context is required, which in this case might not be.

mjkalyan commented 1 year ago

Okay thanks I found it... My first grep didn't find anything somehow (due to a dumb user I guess).

I don't think a window context is needed but an audio context probably is - I'll try it and report back.

mjkalyan commented 1 year ago

I added the default-unload for music yesterday but that wasn't the issue. I'll see what I can find with GDB.

shelvick commented 1 year ago

Okay, I was able to reproduce your crash at the REPL. The short answer is that, somewhere along the line, you're initializing the audio device twice. For whatever reason it's not getting closed when you quit, or not getting closed completely. Two recommendations:

  1. Initialize the audio device by default in with-window, unless there's a reason not to.
  2. When you initialize it, check with is-audio-device-ready-p to ensure you don't init it twice.

If that doesn't stop the crashes, then we'll have to do something more aggressive, like force closing it again before initialization. In my tests I could not trigger a crash by closing an uninitialized audio device, so that should be safe.

mjkalyan commented 1 year ago

Okay I'm on it!

mjkalyan commented 1 year ago

Okay, that seems to have worked and uncovered another error. Now, on the second run, the REPL doesn't hang but reports an unhandled memory error when calling clear-background. I've only tried it 4 times so far, I think it's consistent. I'll commit the changes here for you to see and continue with this new issue.

shelvick commented 1 year ago

On both examples or just module-playing?

mjkalyan commented 1 year ago

Both audio examples on the second run.

shelvick commented 1 year ago

Do any other examples break? Because if so, we can narrow it down to one of the core changes in this PR. We're using clear-background in I think literally every example. Most likely it's an audio-related memory thing that's only just happening to get triggered at that time.

mjkalyan commented 1 year ago

I tried a handful of examples at random and they work on the 1st and second runs (and are obviously using clear-background). I figured that but it's good to be sure.

mjkalyan commented 1 year ago

Hmm.. Something changed and now I'm just getting a memory error reported at main's invocation for both audio examples on the 2nd run. It makes sense that's it's not related to clear-background I just don't know what I did differently. I've been restarting lisp and clearing FASL files and trying examples so something along the way changed the error.

Okay and just as I write this I got back to a hung REPL on the 2nd run of music-stream.lisp for the first time since switch the audio device init to with-window. :thinking:

shelvick commented 1 year ago

Try force-closing the audio device every time before you open it. Hacky, but if it stops crashing...

mjkalyan commented 1 year ago

Okay I'm trying to collect a bunch of data while trying different things to find a pattern. Bear with me. I've tried force closing but I am still getting one of a few errors at different places with no discernible pattern yet. Hence the data collection, I'm just methodically going through a bunch of tests.

mjkalyan commented 1 year ago

What I've got so far... I have a feeling error A and A.1 are the same but I differentiate anyways because Lisp reports A.1 as more specific to clear-background. It's a bit tedious to delete the FASLs each time but I have to control for all mysteries. I think there're some hints in here to start digesting and I'll try to do that before collecting more data - because I'm bored, frankly.

Source for force closing audio device

(defmacro with-window ((&key
                          (width *screen-width*)
                          (height *screen-height*)
                          (title "")
                          (fps *target-fps*)
                          (flags ())
                          (min-size ())
                          exit-key)
                       &body body)
  `(progn
     (claylib/ll:init-window ,width ,height ,title)
     (claylib/ll:close-audio-device) ; *** HERE
     (claylib/ll:init-audio-device)  ; *** HERE
     (claylib/ll:set-target-fps ,fps)
     (setf +default-font+ (load-font-default))
     (gui-load-style-default)
     ,(when flags
        `(claylib/ll:set-config-flags (reduce #'+ ,flags)))
     ,(when min-size
        `(claylib/ll:set-window-min-size ,(car min-size) ,(cadr min-size)))
     ,(when exit-key
        `(claylib/ll:set-exit-key ,exit-key))
     ,@body
     (claylib/ll:close-audio-device) ; *** HERE
     (when (is-window-ready-p)
       (close-window))))

Method: quit lisp; delete fasls; start lisp; quickload examples; run =music-stream.lisp= with runtime variations as noted; exit, reload, and re-run =music-stream.lisp=; observe errors on start or on exit

| Error types |                                                         |
| A           | Unhandled memory fault at #x0 (main ... (with-drawing)) |
| A.1         | Unhandled memory fault at #x0 (clear-background)        |
| B           | REPL hang                                               |

 | Force closing? | 1st run variation            | 2nd run start error | 2nd run exit error | Tally |
 |----------------+------------------------------+---------------------+--------------------+-------|
 | y              | exit after ~5s               | A                   |                    |     4 |
 | y              | exit after ~5s               | A.1                 |                    |     1 |
 |----------------+------------------------------+---------------------+--------------------+-------|
 | y              | SPC after ~5s, then exit     |                     | B                  |     3 |
 | y              | SPC after ~5s, then exit     | A                   |                    |     1 |
 |----------------+------------------------------+---------------------+--------------------+-------|
 | y              | P after ~5s, then exit       | A                   |                    |     2 |
 | y              | P after ~5s, then exit       | A.1                 |                    |     2 |
 |----------------+------------------------------+---------------------+--------------------+-------|
 | y              | P + P after ~5s, then exit   | A                   |                    |     4 |
 |----------------+------------------------------+---------------------+--------------------+-------|
 | y              | P + SPC after ~5s, then exit | A                   |                    |     4 |
 |----------------+------------------------------+---------------------+--------------------+-------|
 | y              | SPC + P after ~5s, then exit | A                   |                    |     3 |
 | y              | SPC + P after ~5s, then exit | A.1                 |                    |     1 |
 |----------------+------------------------------+---------------------+--------------------+-------|
shelvick commented 1 year ago

Merged and (tentatively) fixed in dev.