I am trying to write a game in Java to learn more about the language. I have recently added sounds and it was working fine until I added background music .WAV (605MB). I have created a separate thread to run the music and I thought that would help as threads shouldn't affect each other's performance due to separate stack memory. I am fairly new to Java so I would appreciate any suggestions. I can cut the file into smaller pieces and loop through them (the game doesn't lag with smaller .WAV files) but I am curious why one thread is affected by another and what could I do differently. I've read that depending on the file size Java allocates resources to different locations, could that mean something? Please find snippets of code where I define Sound Class to read the file and thread definitions.
public class Sound {
Clip clip;
URL soundURL[] = new URL[30]; // store file path
Sound() {
soundURL[0] = getClass().getResource("/sound/BlueBoyAdventure.wav");
soundURL[1] = getClass().getResource("/sound/coin.wav");
soundURL[2] = getClass().getResource("/sound/powerup.wav");
soundURL[3] = getClass().getResource("/sound/unlock.wav");
soundURL[4] = getClass().getResource("/sound/fanfare.wav");
soundURL[5] = getClass().getResource("/sound/ChurchTemplarsMusic.wav");
soundURL[6] = getClass().getResource("/sound/FantasyMusic.wav");
soundURL[7] = getClass().getResource("/sound/DevilEyes.wav");
}
public void setFile(int i) {
try {
AudioInputStream ais = AudioSystem.getAudioInputStream(soundURL[i]);
clip = AudioSystem.getClip();
clip.open(ais);
}catch(Exception e) {
}
}
public void play() {
clip.start();
}
public void loop() {
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
public void stop() {
clip.stop();
}
}
First thread (gameEngine):
public void run() {
double drawInterval = 1000000000/FPS;
double delta = 0;
long lastTime = System.nanoTime();
long currentTime;
long timer = 0;
int drawCount = 0;
while(gameThread != null)
{
currentTime = System.nanoTime();
delta = (currentTime - lastTime) / drawInterval;
timer = (currentTime - lastTime);
lastTime = currentTime;
if(delta >= 1) {
update();
repaint();
delta--;
drawCount ;
}
if(timer >= 1000000000) {
System.out.println("FPS:" drawCount " : " Thread.currentThread().getName());
drawCount = 0;
timer = 0;
}
}
}
Second thread dedicated to music:
public class SecondThread implements Runnable {
Thread musicThread;
//SOUND
Sound sound = new Sound();
public void startMusicThread() {
musicThread = new Thread(this);
musicThread.setName("Music");
musicThread.start();
}
@Override
public void run() {
sound.setFile(7);
sound.play();
sound.loop();
}
and this is where I call threads:
public static void main(String[] args) {
GamePanel gamePanel = new GamePanel();
SecondThread secondThread = new SecondThread();
gamePanel.startGameThread();
secondThread.startMusicThread();
}
CodePudding user response:
That is a truly enormous background music file.
I have created a separate thread to run the music and I thought that would help as threads shouldn't affect each other's performance due to separate stack memory.
Yes, threads have separate stack memory. But your music isn't going into stack memory, it's going to the heap, and the heap is common to the whole JVM -- every thread is going to be using the same heap. (How else could threads access each other's variables?)
You have correctly identified the solution, to break up the background music into smaller parts and load only one or two parts at once.
CodePudding user response:
WAV usually is non-compressed PCM audio data. Your 650 MB is similar to an audio CD, which typically holds one hour of music. If you compress that using MP3 (or even better as OGG), you might roughly get down to 65 MB while keeping an acceptable quality.
I am not sure whether those 65 MB would be sufficiently small to simply play - but then you could still break it down into different tracks and decide which one to play based on game events.