【问题标题】:Why do I get lagspikes from sound?为什么我会从声音中得到滞后峰值?
【发布时间】:2012-09-23 06:01:33
【问题描述】:

我正在用 Java 开发一个游戏,并尝试为它编写一个简单的声音系统,它由两个类文件组成:一个处理它们,一个用于加载每个声音文件。

我的问题是,每隔一段时间我就会遇到一个巨大的延迟,这意味着完全停止大约一两秒钟,真的会打断游戏。我怀疑垃圾控制,但我不完全确定。我唯一知道的事实是问题的根源在于声音。

这是我的 SoundHandler.java:

(声音的加载不重要,据我所知应该与问题无关)

package Classes;

import java.io.*;

import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineEvent;
import javax.sound.sampled.LineListener;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.FloatControl;

public class SoundHandler {

Sound Sounds[] = new Sound[1];

public SoundHandler()
{
    if(!LoadSounds("Sounds.cfg"))
        System.out.print("Failiure upon loading sounds!");
}

public boolean LoadSounds(String FileName)
{
    String line = "";
    String SoundName = "";
    String SoundFile = "";
    String[] token3 = new String[10];
    boolean EndOfFile = false;
    int LineCount = 0;
    BufferedReader characterfile = null;

    try
    {
        characterfile = new BufferedReader(new FileReader(GameMain.GameFolder+"Data/"+FileName));
    }
        catch(FileNotFoundException fileex)
        {
            System.out.println(FileName+": file not found.");
            return false;
        }
    while(!EndOfFile && line != null)
    {
        try
        {
            line = characterfile.readLine();
            if(line != null)
            {
                if(line.indexOf("//") == -1 && !line.equals(""))
                    LineCount++;
            }
        }
            catch(IOException ioexception)
            {
                if(LineCount == 0)
                {
                    System.out.println(FileName+": error loading file.");
                    return false;
                }
                EndOfFile = true;
            }
    }
    try { characterfile.close(); } catch(IOException ioexception) { characterfile = null; }

    Sounds = new Sound[LineCount];
    EndOfFile = false;
    LineCount = 0;

    try
    {
        characterfile = new BufferedReader(new FileReader(GameMain.GameFolder+"Data/"+FileName));
    }
        catch(FileNotFoundException fileex)
        {
            System.out.println(FileName+": file not found.");
            return false;
        }

    try
    {
        line = characterfile.readLine();
        if(line != null)
            if(line.indexOf("//") == -1 && !line.equals(""))
                LineCount++;
    }
        catch(IOException ioexception) { }

    while(EndOfFile == false && line != null) {
        if(line.indexOf("//") == -1 && !line.equals(""))
        {
            line = line.trim();
            line = line.replaceAll("\t\t", "\t");
            line = line.replaceAll("\t\t", "\t");
            line = line.replaceAll("\t\t", "\t");
            line = line.replaceAll("\t\t", "\t");

            int Spot = line.indexOf("\t");
            SoundName = line.substring(0,Spot);
            SoundFile = line.substring(Spot+1);
            Sounds[LineCount-1] = new Sound(SoundName,SoundFile);
        }

            try {
                    line = characterfile.readLine();
                    if(line != null)
                        if(line.indexOf("//") == -1 && !line.equals(""))
                            LineCount++;
            } catch(IOException ioexception1) { EndOfFile = true; }
    }
    try { characterfile.close(); } catch(IOException ioexception) { }
    return true;
}

public File GetSoundFile(String Name)
{
    File result = null;
    for(int i = 0; i < Sounds.length; i++)
        if(Sounds[i].Name.equals(Name))
            result = Sounds[i].File;
    return result;
}

public Sound GetSound(String Name)
{
    Sound result = null;
    for(int i = 0; i < Sounds.length; i++)
        if(Sounds[i].Name.equals(Name))
            result = Sounds[i];
    return result;
}

public int GetSoundID(String Name)
{
    int result = 0;
    for(int i = 0; i < Sounds.length; i++)
        if(Sounds[i].Name.equals(Name))
            result = i;
    return result;
}

Double MasterVolume = 0.75;

public float CalcVolume(double Vol)
{
    float result = 0f;
    result = -40.0f + (float)(MasterVolume*Vol*40);
    if(result < -40.0f)
        result = -40.0f;
    if(result > 0.0f)
        result = 0.0f;
    return result;
}

public boolean PlaySound(String SoundName, double Vol)
{
    int ID = GetSoundID(SoundName);

    try
    {
        Clip CurrentClip;
        Sounds[ID].Reset(false);
        CurrentClip = (Clip) AudioSystem.getLine(Sounds[ID].info);
        CurrentClip.addLineListener(new LineListener() {
            public void update(LineEvent event) {
                if (event.getType() == LineEvent.Type.STOP) {
                    event.getLine().close();
                }
            }
        });
        CurrentClip.open(Sounds[ID].sound);

        FloatControl Volume;
        Volume = (FloatControl) CurrentClip.getControl(FloatControl.Type.MASTER_GAIN);
        Volume.setValue(CalcVolume(Vol));
        CurrentClip.start();
    }
    catch(LineUnavailableException e) { e.printStackTrace(); }
    catch(IOException e) { e.printStackTrace(); }

    return true;
}
}

这是我的 Sound.java:

package Classes;

import java.io.File;
import java.io.IOException;

import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;

public class Sound {

public String Name = "";
public File File = null;

AudioInputStream sound;
DataLine.Info info;
Clip clip;

public Sound(String iName, String FileName)
{
    Name = iName;
    File = new File(GameMain.GameFolder+"Sound/"+FileName+".wav");
    Reset(true);
}

public void Reset(boolean init)
{
    try
    {
        if(!init)
            sound.close();
        sound = AudioSystem.getAudioInputStream(File);
        info = new DataLine.Info(Clip.class, sound.getFormat());
    }
    catch(IOException e) { e.printStackTrace(); }
    catch(UnsupportedAudioFileException e) { e.printStackTrace(); }
}
}

我尝试过寻找一种在游戏中实现声音的通用方法,但我遇到的大多数都没有同时运行同一个声音文件的多个实例,这就是我目前所拥有的。我敢肯定有一些微小的低效率,尤其是在加载代码中,但我肯定漏掉了一些漏洞。也欢迎任何有关自定义 GC 使用的提示。 提前致谢。

【问题讨论】:

  • 声音缓冲/播放是否在单独的线程中运行?
  • 是的,游戏使用swing,全屏,jpanel作为contentpane。我不完全确定声音在编程中是如何工作的,但据我所知,它不在单独的线程上。当声音播放时,它似乎并没有特别滞后,但过了一段时间(一分钟左右),似乎有些东西加起来并以滞后的方式释放。我现在会尝试添加一个线程,看看是否有帮助。
  • 我了解到 Clip 会为每个播放的声音启动一个单独的线程。我也将声音处理程序分离到另一个线程中,但我在尝试使其与主线程通信时遇到了问题。我确实搜索了一些例子,但我想要的是命令一个 void 函数在主线程的 soundhandler 线程中运行,但我不知道该怎么做。

标签: java audio lag


【解决方案1】:

在 Java Oracle 网站上研究并发线程可能更容易...我可以得到一个链接。有多种方法可以将线程同步在一起,并且它们确实有示例。

Oracle Concurrency Documenation! ->> Object Syncing

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-14
    • 2020-04-07
    • 1970-01-01
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多