al_uninstall_audio - what exactly happens?
roger levy

Do samples get freed? What would happen if I uninstalled the audio system while a game was running and then re-installed it? Is that standard practice, in order to cut audio when say for instance the window loses focus? (To save CPU - I noticed that it seems to take up a certain percentage of CPU even when no sounds are being played)

amarillion

How do you know that it's the audio system that is consuming the CPU?

roger levy

If I don't install it to begin with the CPU usage is much lower when the window doesn't have focus. I pause the game loop when it loses focus - it's 6-8% with audio, 1-2% without. (This might sound like a small difference but keep in mind I have 8 cores so I think "100%" is 12.5%.)

edit: also, since my language includes a REPL I can just manually install it to watch the change in realtime, which I just did to confirm and it's still doing it.

edit 2: i looked at my audio init function and i found the source of the CPU spike. i was reserving thousands of samples with al_reserve_sample! don't ask me how or why... has to do with fixed-point numbers :P

edit 3: still, there is still a 1-2% bump (out of 12.5%!) in CPU even with nothing playing.

Elias

Allegro's mixer thread and timer thread are both still running consuming CPU. On Android, I do this on ALLEGRO_EVENT_DISPLAY_HALT_DRAWING:

ALLEGRO_MIXER *mixer = al_get_default_mixer();
if (mixer) al_set_mixer_playing(mixer, false);
al_set_default_voice(NULL);
al_stop_timer(timer);

This gets my CPU usage to 0.0%. The timer is my single Allegro timer I use for timing.

And I do this on ALLEGRO_EVENT_DISPLAY_RESUME_DRAWING:

roger levy

@Elias Thanks. You saved me some time. I'll implement this.

EDIT: What does the al_set_default_voice call do? Did you mean al_set_default_mixer?

EDIT 2: Nvm, checked the 5.2.2 dox. Turns out something else seems to be eating up the CPU even when the game is suspended :/

Elias

Can you post your event loop? Are any events still being generated after you stop all timers?

Also, if this is Windows, try using OpenGL instead of DirectX, just to see if it makes a difference. I don't know anything about the Windows port myself but I saw some posts about DirectX causing some strange CPU usage in some cases.

roger levy

I'm using OpenGL. I'll post the loop, but it's in Forth, so, assuming you don't know it ... sorry. Maybe you'll be able to figure it out still. Just read the code from left to right, each word separated by spaces is a function call. With the exception of: : if then begin while repeat again do loop case endcase of endof which are flow control keywords. The one weirdness is then which means "and then", think of it as "endif".

\ Universal main loop
\  Skips rendering frames if logic takes too long (up to 4 frames are skipped)
\  You can disable the frame timer to save CPU when making editors etc
\  When the window is switched away from the timer will be disabled, and re-enabled when
\    it regains focus.
\  The loop has some common controls:
\    F12 - break the loop
\    F4 - quit the process
\    ALT-ENTER - toggle fullscreen
\    TILDE - toggles a flag called INFO, doesn't do anything on its own.

\ Values
0 value #frames \ frame counter.
0 value renderr
0 value steperr
0 value alt?  \ part of fix for alt-enter bug when game doesn't have focus
0 value breaking?
0 value lag  \ completed ticks
0 value 'go
0 value 'step
0 value 'render

\ Flags
variable info  \ enables debugging mode display
variable allowwin  allowwin on
variable fs    \ is fullscreen enabled?

create fse  /ALLEGRO_ANY_EVENT /allot  \ fullscreen event
#999 constant EVENT_FULLSCREEN 

: poll  pollKB  pollJoys  [defined] dev [if] pause [then] ;
: break  true to breaking? ;
: -break  false to breaking? ;
: unmount  ( -- )   1-1   0 0 displayw displayh al_set_clipping_rectangle ;

[defined] dev [if]
    variable (sp)
    : try  dup -exit  sp@ >r  ['] call catch (sp) !  r> sp!  (sp) @ ;
[else]
    : try  dup -exit call 0 ;
[then]
    : try  dup -exit call 0 ;

private:
    \ : alt?  e ALLEGRO_KEYBOARD_EVENT-modifiers @ ALLEGRO_KEYMOD_ALT and ;
    : std
      etype ALLEGRO_EVENT_DISPLAY_RESIZE = if
        -timer  display al_acknowledge_resize  +timer  \ we have to turn off the timer to avoid a race condition
                                                       \ where bitmaps aren't recreated before trying to draw to them
      then
      etype ALLEGRO_EVENT_DISPLAY_SWITCH_OUT = if  -timer  -audio  then
      etype ALLEGRO_EVENT_DISPLAY_SWITCH_IN = if  clearkb  +timer   +audio  false to alt?  then
      etype ALLEGRO_EVENT_DISPLAY_CLOSE = if  0 ExitProcess  then
      etype ALLEGRO_EVENT_KEY_DOWN = if
        e ALLEGRO_KEYBOARD_EVENT-keycode @ case
          <alt>    of  true to alt?  endof
          <altgr>  of  true to alt?  endof
          <enter>  of  alt? -exit  fs toggle  endof
          <f4>     of  alt? -exit  0 ExitProcess endof
          <f5>     of  refresh  endof
          <f12>    of  break  endof
          <tilde>  of  alt? -exit  info toggle  endof
        endcase
      then
      etype ALLEGRO_EVENT_KEY_UP = if
        e ALLEGRO_KEYBOARD_EVENT-keycode @ case
          <alt>    of  false to alt?  endof
          <altgr>  of  false to alt?  endof
        endcase
      then ;
public:


: fsflag  fs @ allowwin @ not or ;
: ?fserr  0= if fs off  " Fullscreen is not supported by your driver." alert  then ;
variable winx  variable winy
: ?poswin   \ save/restore window position when toggling in and out of fullscreen
    display al_get_display_flags ALLEGRO_FULLSCREEN_WINDOW and if
        fs @ 0= if  r> call  display winx @ winy @ al_set_window_position  then
    else
        fs @ if     display winx winy al_get_window_position  then
    then ;

variable newfs
: ?fs
    ?poswin  display ALLEGRO_FULLSCREEN_WINDOW fsflag al_toggle_display_flag ?fserr
    fs @  newfs @  <> if
        fse EVENT_FULLSCREEN emit-user-event
    then
    fs @ newfs ! ;

defer ?overlay  ' noop is ?overlay  \ render ide
defer ?system   ' noop is ?system   \ system events

private:
    : update?  timer? if  lag dup -exit drop  then  eventq al_is_event_queue_empty  lag 4 >= or ;
    : wait  eventq e al_wait_for_event ;
    : render  ?fs  unmount  'render try to renderr  unmount  ?overlay  al_flip_display  0 to lag ;
    : ?render  update? -exit  1 +to #frames  render ;
    : ?step  etype ALLEGRO_EVENT_TIMER = if  poll  1 +to lag   'step try to steperr  then ;
    : /ok  resetkb  -break  >display  +timer  render ;
    : ok/  eventq al_flush_event_queue -timer  >ide  -break ;
public:

: render>  r>  to 'render ;  ( -- <code> )  ( -- )
: step>  r>  to 'step ;  ( -- <code> )  ( -- )
: go>  r> to 'go   0 to 'step ;  ( -- <code> )  ( -- )

: ok
    /ok
    begin
        wait
        begin
            std  ?system  'go try drop  ?step  ?render
            eventq e al_get_next_event 0=  breaking? or
        until  ?render  \ again for sans timer
    breaking? until
    ok/ ;

Elias

I wrote several Forth implementations so I know about reading Forth :D

Can you add a debug print to see if you are still getting timer events (or any other events) while your program is suspended?

roger levy

That's awesome! Same here. I feel like Forth has been getting gradually more well-known after being treated like an anathema for years, so to me this was the definitive confirmation that it's turning around, haha. Been in love since 2000. (I post frequently on the Forth Programming Facebook group if you want to be up-to-date on my doings... I'm finalizing a framework for game-and-engine development... also check out rogerlevy/bubble-internal on Github...)

I'll try your suggestion... will post an update later today.

Thread #616932. Printed from Allegro.cc