Libgdx sound lag? [solved]

I’ve been working the kinks out of my game that I’ve been working on ON an OFF for quite some time and now I’m reaching the end. I’ve noticed that, while the game runs perfectly fine on my POS PC, I am getting lag whenever I play it on android. The point of this game is to destroy products on shelves, and when they are destroyed, they play a crumble sound with a randomized pitch. Something like 5 or 6 products are all destroyed at the same time. At first, I thought this issue was from all the particles I spawn when the products are destroyed, but I quickly learned that when I disabled in-game sound, I had no more lag. I was wondering if anyone else has had this kind of trouble with sound and libgdx. If necessary, I’ll post some code later. Thanks in advance.

the sound playback makes the game lag huh ?

try some other sound files instead. try some wav pcm since those are the most raw and dont have to be decoded I guess
I use OGG only and never had that happen. of course those POS PCs could suck and of course do sound software side via CPU and drain performance

I just checked the format on that sound, and ironically, it’s one a wav. I’ll try converting it over to OGG later. Also, I’m not having any performance trouble on PC, only android.

Do you mean sound lag, or just that the game runs slowly? (Which is not “lag”, that’s what “gamers” think it’s called because they don’t have any technical knowledge)

Cas :slight_smile:

Well, yeah I guess it would just be running slowly. There’s not any noticable latency between when the sound is supposed to play and when the sound actually plays. Sorry for the misnomer there.

I’d be interested in seeing the code.

You might find the following article interesting, in terms of understanding basic issues pertaining to Java & Sound. Though, it doesn’t specifically go into differences in implementation for Android & Java.

“Real Time Low Latency Audio Processing in Java”
http://quod.lib.umich.edu/cgi/p/pod/dod-idx?c=icmc;idno=bbp2372.2007.131

Keep sure that you are not firing lots of audio events at once. If you have some code bug and you launch even coupple sounds per frame it can be quite problem in longer run and it will sound like garbage.

Well, here’s my Audio.java class. It’s not the greatest, but hey, I’m open for suggestions.

package com.toasted;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.audio.Music;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.files.FileHandle;

public class Audio {
	public static Sound beep0 = newSound("blip.wav");
	public static Sound swing = newSound("swing.wav");
	public static Sound crumble = newSound("crumble.wav");
	public static Sound laser = newSound("laser.wav");
	public static Sound vaporize = newSound("vaporize.wav");
	public static Sound thump = newSound("thump.ogg");
	public static Sound siren = newSound("siren.ogg");
	public static Sound wood = newSound("wood.ogg");
	public static Sound chain = newSound("chain.ogg");
	
	public static Sound whiteSedan = newSound("whiteSedan.ogg");
	public static Sound cleanUp = newSound("cleanUp.ogg");
	public static Sound carl = newSound("carl.ogg");
	public static Sound thankYou = newSound("thankyou.ogg");
	public static Sound dairy = newSound("dairy.ogg");
	public static Sound special = newSound("special.ogg");
	public static Sound cashews = newSound("cashews.ogg");
	
	public static final float cleanUpRuntime = 2.0F;
	public static final float whiteSedanRuntime = 5.0F;
	public static final float carlRuntime = 7.5F;
	public static final float thankYouRuntime = 7.75F;
	public static final float dairyRuntime = 5.75F;
	public static final float specialRuntime = 7.0F;
	public static final float cashewsRuntime = 6.0F;
			
	public static Music gameLoop = Gdx.audio.newMusic(Gdx.files.internal("sound/musicLoop.ogg"));
	public static Music rageMusic = Gdx.audio.newMusic(Gdx.files.internal("sound/rage.ogg"));
	
	public final static float SWING_VOL = .5F;
	public final static float VOL = 1.0F;
	public static boolean enabled = true;
	
	public void pauseAll(){
		beep0.pause();
		swing.pause();
		crumble.pause();
		laser.pause();
		vaporize.pause();
		thump.pause();
		siren.pause();
		wood.pause();
		whiteSedan.pause();
		cleanUp.pause();
		chain.pause();
		
		gameLoop.pause();
		rageMusic.pause();
	}
	
	public static void play(Sound s){
		if(enabled)
			s.play(VOL);
	}
	public static void loop(Sound s){
		if(enabled)
			s.loop(VOL);
	}
	public static void loop(Sound s, float vol){
		if(enabled)
			s.loop(vol);
	}
	public static void play(Music m){
		if(enabled)
			m.play();
	}

	
	public static void playRandomPitch(Sound sound, float vol){
		if(!enabled) return;
		float pitch = Global.r.nextFloat();
		sound.play(vol, (pitch * 1.0F) + 1.0F, 0);
	}
	
	private static Sound newSound(String filename){
		return Gdx.audio.newSound(Gdx.files.internal("sound/"+filename));
	}
}

And this is where I believe I’m seeing my problem.

for(int i = 0;i < products.size();i++){
			Product p = products.get(i);
			if(p.position.x < player.position.x && player.position.x - p.position.x > 32){
				products.remove(p);
			}
			if(!p.exists()){
				//shatter
				for(int j = 0;j < 5;j++){
					particles.add(new Particle(p.position, new Vec2D(Global.getRandomInt(1, 10), 0), 2.0F, true, Art.frag(p.item)));
				}
				productCounter[p.ID]++; 
				products.remove(p);
				Global.score += (int)Global.multiplier * Product.points[p.ID];
				if(p.sliced) {
					rage += 1 * (Global.crown ? 1.5F : 1F);
					Audio.playRandomPitch(Audio.crumble, .25F);
				}else{
					switch(rageType){
					case lazerVision:
						Audio.play(Audio.vaporize);
						break;
					}
				}
				if(rage > 100){
					rage = 100;
				}
			}
		}

My first guess is that your Android device has considerably less processing power than your PC, and that this accounts for the difference in performance.

Decoding a compressed file takes much more processing than running a wav. If you are trying to do both at the same time, or even just trying to play more than one ogg at once, that could very well be “too much” for your Android device while still being within the capabilities of your PC. (My old PC, from 2004, starts to bog down even with two compressed files playing at the same time. I assume a newer PC can handle considerably more than that.) I don’t know what to suggest beyond either trying to create a less ambitious score, or trying to find some way of using less compression, e.g., decompressing and working from the unpacked file stored in memory (uses a lot of memory, yes).

Another remote possibility is that using some sort of mixer rather than running all the files individually might add some efficiency. But I’ve only done this using Java on PCs, not on Android. I do not know if, for example, the TinySound library could be wrappered or revised to run on Android, or if doing so would help.

Warning: my lack of experience with Android sound means that I could well be overlooking an Android-specific bug. But my general experience with sound leads me to suspect you are trying to do “too much”.

Well I’m fairly certain that the issue is NOT with the phone lacking power. It’s a newer Samsung Galaxy S4, and I’ve also run it on a couple of other newer phones as well.

You could well be right. Is there a way to profile the program and verify that?

Success has been had! I lowered the sample rate on the clip from about 96k to 44.1k. It plays perfectly fine now!

Congratulations!

Did the same code on the PC run clips with a sample rate of 96000? I didn’t know Java on PCs could manage 96000Hz. Is this new to Java? Did you do anything special to allow this? Is there something built into LIBGDX that allows it to do this?

Yeah, the clip ran perfectly fine on PC. I know I didn’t do anything special for it because I downloaded it from freesound and didn’t even look at the sample rate until there was an issue.