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)
How do you know that it's the audio system that is consuming the CPU?
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
edit 3: still, there is still a 1-2% bump (out of 12.5%!) in CPU even with nothing playing.
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:
al_restore_default_mixer(); ALLEGRO_MIXER *mixer = al_get_default_mixer(); if (mixer) al_set_mixer_playing(mixer, true); al_start_timer(timer);
@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 :/
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.
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/ ;
I wrote several Forth implementations so I know about reading Forth
Can you add a debug print to see if you are still getting timer events (or any other events) while your program is suspended?
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.