PlaySound causing low framerate first time a sound is played

Started by TomToad, August 28, 2020, 21:27:54

Previous topic - Next topic

TomToad

When playing a sound first time, the framerate drops for a second.  After that, the same sound can be played multiple times without problem.  I tried delaying a few seconds to give time for  the sounds to load, but that doesn't seem to help any.
 
ANyone have a solution that doesn't involve playing all sounds before the game begins?

The example code below shows the problem in action.  The bunny and sound is from Kenney's Assets.
Code (blitzmax) Select
SuperStrict

Local gravity:Double = 2.0
Local speed:Double = 0.0
Local y:Double = 10
Local image:TImage = LoadImage("bunny1_jump.png")
Local JumpSound:TSound = LoadSound("drop_003.ogg")
Local Channel:TChannel = AllocChannel()

Graphics 1024,768
Local delta:Double
Local Time:Int, OldTime:Int = MilliSecs()

While Not KeyHit(KEY_ESCAPE) And Not AppTerminate()
Time = MilliSecs()
delta = (TIme-OldTIme)/1000.0
OldTime = Time

speed :+ gravity
y :+ speed
If y > 768-image.height
y = 768-image.height
speed = -50
PlaySound(JumpSOund, Channel)
EndIf

Cls
DrawImage image,512,y
Flip
Wend

------------------------------------------------
8 rabbits equals 1 rabbyte.

Matty

While not a solution that doesn't involve playing all sounds-if you do that then you can always set the volume to inaudible while doing so such that the player does not notice.

A similar thing occurs with some 3d libraries for android where the first appearance of a resource causes the app to pause while caching the resource.  In such cases spinning around the world and hiding the rendered world behind a bitmap for a second does the trick.

Derron

Uhm... for what thing we have to look for?

Jumps perfectly smooth and does play "bobb bobbb bobbb bobbb" sounds - right from the start. (Linux Mint 19, 64bit).

Can you add a "log" so we see times per "frame"? Does it happen without audio too?
What happens if you do set the audio driver manually?

SetAudioDriver(the one you use - freeaudio, soloud...)



bye
Ron

Henri

Hi,

I have a SSD drive so I couldn't re-produce your issue. I suspect that if your description is right the sound is played from the HD the first time and from memory afterwards.

There is a CueSound function though. Would that do the trick ?

-Henri
- Got 01100011 problems, but the bit ain't 00000001

Derron

I thought "LoadSound" alread loads the file into memory.

You could check it out by doing this:

loca t:TSound = LoadSound("bla.ogg")
Delay(10000)
PlaySound(t)

and while it delays... rename your bla.ogg to bla2.ogg (file handle would become invalid).


Just checked it out and ... sound still played.
And as Henri wrote: CueSound is your friend in some cases.

https://blitzmax.org/docs/en/api/brl/brl.audio/

But AllocChannel should ... do the same too, so ... maybe (and as stated already) try out a different audio backend ("Soloud")


Import audio.soloudaudio
Import audio.soloudaudiominiaudio 'miniaudio backend
'Import audio.soloudaudiosdl 'sdl backend
SetAudioDriver("Soloud")


bye
Ron

TomToad

Quote from: Derron on August 29, 2020, 07:28:26
What happens if you do set the audio driver manually?

SetAudioDriver(the one you use - freeaudio, soloud...)

Seems to be a driver issue.  Problem exists when using "DirectSound" but goes away with any other driver.  Even "FreeAudio DirectSound" works ok.

Thanks :)
------------------------------------------------
8 rabbits equals 1 rabbyte.

Derron

With Soloud you could even "stream" the audio.


@GfK:
Did not check it indepth but If a am right, then default (freeaudio etc) is that ogg files get decoded in "LoadAudio", not when actually playing the audio.

If unsure, just add 10 of "loadsound()" with your favorite ogg/mp3 files ... and measure how long it takes - if it is decoded "on playback", there should be <1ms for all of the files.


I think it is more plausible that the directsound thing requires some init which is does not when "initializing" is done from the backend of BlitzMax / "brl drivers".


Meanwhile (if not wanting to change backend audio driver) pne could ... create a "silent" audio file ... incbin it and play this file then right on start. So "later" there can be no hickup.

bye
Ron

fielder

are you sure that the sound is played JUST 1 time? and not 5-6 times (just looking code)
usually on my games i place a timer sound to prevent that the same sound can't be played again before 500millisecs

Derron

If each bullet you fire should play a sound, then you should not limit it.
But if each startAttack does plays a sound and startAttack is called on each keyhit, then yes, play only if channel is free again.

Bye
Ron

TomToad

Done a bit of experimenting with this.  First, I only have problems with the default "DirectSound" driver.  Other drivers do not exhibit this problem.  It is not a compression thing as it makes no difference whether I use an .ogg or a .wav file.

The delay happens within PlaySound or ResumeChannel.  If I set a timer before the call and right after the call, I find a delay of about 250-500 milliseconds.  It has nothing to do with loading, initializing, nor decompressing the sound, because when I add a delay between loading/cuing sounds and playing the sound, there still is a delay.

This only occurs on the very first playing of a sound.  Subsequent plays are instant regardless of sound or channel.  This makes me think that DirectSound is loading/initializing only when the first sound needs to play creating the delay.

Solution is 1) use a driver other than DirectSound or 2) play a blank sound or a sound that can be delayed a bit (such as intro music) first.


------------------------------------------------
8 rabbits equals 1 rabbyte.