Java音频在定制的声音类中不断发出噼啪声

Java音频在定制的声音类中不断发出噼啪声,java,multithreading,audio,Java,Multithreading,Audio,为了保持简洁,我使用了一个自定义的Java声音类,但是我使用它的方式,出于某种原因,它会为某些声音产生大量的噼啪声。如果上传音频可能有帮助,请让我知道 这是我正在使用的Sound类的代码: package brad.classes; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayL

为了保持简洁,我使用了一个自定义的Java声音类,但是我使用它的方式,出于某种原因,它会为某些声音产生大量的噼啪声。如果上传音频可能有帮助,请让我知道

这是我正在使用的Sound类的代码:

package brad.classes;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

import sun.audio.AudioData;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;
import sun.audio.ContinuousAudioDataStream;

/*
 * Custom class for playing audio (audio file must be in src)
 */
public class Sound {
    private ContinuousAudioDataStream loop = null; //Puts music data into loop
    private InputStream in = null; //Takes in music file as input
    private AudioStream audioStreamMusic = null; //Takes in InputStream of music file as input
    private AudioData audioData = null; //Changes AudioStream to data
    private boolean loopable; //Whether the music input is meant to be looped or not
    private String music; //The name of the music file
    private double length; //The duration of the audio snippet in seconds
    private static boolean isStopped = false;

    /*
     * Takes in music file name and whether or not the file is loopable
     */
    public Sound(String music, boolean loopable) throws IOException, UnsupportedAudioFileException {
        if(music.length() < 4 || !music.substring(music.length() - 4, music.length()).equals(".wav"))
            throw new IOException(music + " (Given file must be .wav)");
        else if(new File(music).length() > 1000000)
            throw new IOException(music + " (Given file must not be over 1 megabyte)");
        this.music = System.getProperty("user.dir") + "/" + music;
        this.loopable = loopable;
        in = new FileInputStream(music);
        audioStreamMusic = new AudioStream(in);
        if(loopable) {
            audioData = audioStreamMusic.getData();
            loop = new ContinuousAudioDataStream(audioData);
        }
        AudioInputStream stream = AudioSystem.getAudioInputStream(new File(music));
        AudioFormat format = stream.getFormat();
        long frames = stream.getFrameLength();
        length = (double) frames/format.getFrameRate();
    }

    /*
     * Also takes in whether the file size limit should be ignored
     */
    public Sound(String music, boolean loopable, boolean override) throws IOException {
        if(music.length() < 4 || !music.substring(music.length() - 4, music.length()).equals(".wav"))
            throw new IOException(music + " (Given file must be .wav)");
        if(!override) {
            if(new File(music).length() > 1000000)
                throw new IOException(music + " (Given file must not be over 1 megabyte)");
        }
        this.music = System.getProperty("user.dir") + "/" + music;
        this.loopable = loopable;
        in = new FileInputStream(music);
        audioStreamMusic = new AudioStream(in);
        if(loopable) {
            audioData = audioStreamMusic.getData();
            loop = new ContinuousAudioDataStream(audioData);
        }
    }

    /*
     * Plays audio file
     */
    public void play() {
        if(loopable)
            AudioPlayer.player.start(loop);
        else {
            try {
                in = new FileInputStream(music);
                audioStreamMusic = new AudioStream(in);
                AudioPlayer.player.start(audioStreamMusic);
            }
            catch(IOException error) {
                System.out.println(error);
            }
        }
    }

    /*
     * Stops audio file if playing
     */
    public void stop() {
        if(loopable)
            AudioPlayer.player.stop(loop);
        else
            AudioPlayer.player.stop(audioStreamMusic);
    }

    /*
     * Returns a string representation of the sound, including
     * the given name of the audio file as well as whether or
     * not it is loopable
     */
    @Override
    public String toString() {
        return String.format("Sound[music = %s, loopable = %b]", music, loopable);
    }

    public boolean equals(Sound other) {
        if(music.equals(other.music))
            return true;
        return false;
    }

    /*
     * Returns value of music
     */
    public String getMusic() {
        return music;
    }

    /*
     * Returns value of loopable
     */
    public boolean getLoopable() {
        return loopable;
    }

    /*
     * Returns value of length
     */
    public double getLength() {
        return length;
    }

    /*
     * Plays group of Sounds
     */
    public static Thread playGroup(Sound[] sounds, boolean loopable) throws InterruptedException {
        return playGroup(new ArrayList<Sound>(Arrays.asList(sounds)), loopable);
    }

    /*
     * Plays group of Sounds
     */
    public static Thread playGroup(ArrayList<Sound> sounds, boolean loopable) throws InterruptedException {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                do {
                    int i = 0;
                    try {
                        sounds.get(0).play();
                        Thread.sleep((long) (sounds.get(0).getLength() * 1000));
                        for(i = 1; i < sounds.size(); ++i) {
                            sounds.get(i).play();
                            sounds.get(i - 1).stop();
                            Thread.sleep((long) (sounds.get(i).getLength() * 1000));
                        }
                    }
                    catch(Exception e) {
                        sounds.get(i).stop();
                        break;
                    }
                } while(loopable && !isStopped);
            }
        };
        Thread t = new Thread(r);
        t.start();
        return t;
    }

    public static void stopGroup(Thread t) {
        while(t != null && !t.isInterrupted()) {
            t.interrupt();
            isStopped = true;
        }
    }
}
package.class;
导入java.io.File;
导入java.io.FileInputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.util.ArrayList;
导入java.util.array;
导入javax.sound.sampled.AudioFormat;
导入javax.sound.sampled.AudioInputStream;
导入javax.sound.sampled.AudioSystem;
导入javax.sound.sampled.unsupportDaudioFileException;
导入sun.audio.AudioData;
导入sun.audio.AudioPlayer;
导入sun.audio.AudioStream;
导入sun.audio.ContinuousAudioDataStream;
/*
*用于播放音频的自定义类(音频文件必须在src中)
*/
公共级音响{
private ContinuousAudioDataStream loop=null;//将音乐数据放入循环中
private InputStream in=null;//接收音乐文件作为输入
private AudioStream audioStreamMusic=null;//接收音乐文件的InputStream作为输入
私有AudioData AudioData=null;//将AudioStream更改为数据
private boolean loopable;//音乐输入是否要循环
私有字符串音乐;//音乐文件的名称
private double length;//音频片段的持续时间(秒)
私有静态布尔值=false;
/*
*接收音乐文件名以及该文件是否可循环
*/
公共声音(字符串音乐,布尔循环)引发IOException,UnsupportdAudioFileException{
if(music.length()<4 | |!music.substring(music.length()-4,music.length()).equals(“.wav”))
抛出新IOException(music+“(给定文件必须是.wav)”);
else if(新文件(music).length()>1000000)
抛出新IOException(music+(给定文件不得超过1兆字节));
this.music=System.getProperty(“user.dir”)+“/”music;
this.loopable=可循环;
in=新文件输入流(音乐);
audioStreamMusic=新的音频流(in);
if(可循环){
audioData=audioStreamMusic.getData();
loop=新的连续音频数据流(音频数据);
}
AudioInputStream=AudioSystem.getAudioInputStream(新文件(音乐));
AudioFormat=stream.getFormat();
长帧=stream.getFrameLength();
长度=(双)帧/format.getFrameRate();
}
/*
*还考虑是否应忽略文件大小限制
*/
公共声音(字符串音乐、布尔循环、布尔覆盖)引发IOException{
if(music.length()<4 | |!music.substring(music.length()-4,music.length()).equals(“.wav”))
抛出新IOException(music+“(给定文件必须是.wav)”);
如果(!覆盖){
if(新文件(music).length()>1000000)
抛出新IOException(music+(给定文件不得超过1兆字节));
}
this.music=System.getProperty(“user.dir”)+“/”music;
this.loopable=可循环;
in=新文件输入流(音乐);
audioStreamMusic=新的音频流(in);
if(可循环){
audioData=audioStreamMusic.getData();
loop=新的连续音频数据流(音频数据);
}
}
/*
*播放音频文件
*/
公共游戏{
if(可循环)
AudioPlayer.player.start(循环);
否则{
试一试{
in=新文件输入流(音乐);
audioStreamMusic=新的音频流(in);
AudioPlayer.player.start(audioStreamMusic);
}
捕获(IOException错误){
系统输出打印项次(错误);
}
}
}
/*
*播放时停止音频文件
*/
公共停车场(){
if(可循环)
音频播放器。播放器。停止(循环);
其他的
AudioPlayer.player.stop(audioStreamMusic);
}
/*
*返回声音的字符串表示形式,包括
*音频文件的给定名称,以及是否
*不是,它是可循环的
*/
@凌驾
公共字符串toString(){
返回String.format(“声音[music=%s,loopable=%b]”,music,loopable);
}
公共布尔等于(声音其他){
如果(音乐等于(其他音乐))
返回true;
返回false;
}
/*
*返回音乐的价值
*/
公共字符串getMusic(){
回归音乐;
}
/*
*返回loopable的值
*/
公共布尔getLoopable(){
返回循环;
}
/*
*返回长度的值
*/
公共双getLength(){
返回长度;
}
/*
*播放一组声音
*/
公共静态线程播放组(Sound[]sounds,boolean loopable)抛出InterruptedException{
返回播放组(新的ArrayList(Arrays.asList(sounds)),可循环);
}
/*
*播放一组声音
*/
公共静态线程播放组(ArrayList声音,布尔循环)抛出InterruptedException{
Runnable r=新的Runnable(){
@凌驾
公开募捐{
做{
int i=0;
试一试{
sounds.get(0.play();
sleep((长)(sounds.get(0.getLength()*1000));
对于(i=1;ipackage defense;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontFormatException;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.imageio.ImageIO;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import brad.classes.Sound;

public class Runner extends JPanel implements ActionListener, KeyListener {
    private static final long serialVersionUID = 1L;

    static char dir = 'u';

    static int delay = 10;
    static int angle = 0;
    static int breakCount = 0;
    static int breakFrame = 0;
    static int count = 0;
    static int gifCount = 0;
    static int currentDirection = 0;
    static int gameOverCount = 0;
    static int gameOverFrame = 0;

    static boolean isHard = true;
    static boolean runsGif = false;
    static boolean heartDone = false;
    static boolean gameOverDone = false;
    static boolean firstEnd = true;
    static boolean secondEnd = true;

    protected Timer timer;

    BufferedImage gif;
    BufferedImage heart;
    BufferedImage heartBreak;
    BufferedImage gameOver;

    static Thread mainSound;

    Attack a1 = new Attack(new LinkedList<Arrow>(), 2);
    Player p = new Player();

    public Runner(String s) {
        JFrame frame = new JFrame(s);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Runner bp = new Runner();
        frame.add(bp);
        frame.addKeyListener(this);
        frame.setSize(600, 600);
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        frame.setSize(600, 600);
        frame.setLocation(dim.width/2 - frame.getSize().width/2, dim.height/2 - frame.getSize().height/2);
        frame.setResizable(false);
        frame.setVisible(true); 
    }

    public static void main(String args[]) throws IOException, UnsupportedAudioFileException, InterruptedException {
        @SuppressWarnings("unused")
        Runner a = new Runner("Game");
        ArrayList<Sound> mainTheme = new ArrayList<Sound>();
        int max;
        String base;
        if(isHard) {
            max = 16;
            base = "BATH";
        }
        else {
            max = 12;
            base = "SOJ";
        }
        for(int i = 1; i <= max; ++i) {
            mainTheme.add(new Sound("audio/" + base + i + ".wav", false));
        }
        mainSound = Sound.playGroup(mainTheme, true);
    }

    public Runner() {
        timer = new Timer(delay, this);
        timer.start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if(p.getHealth() != 0) {
            drawBG(g);
            drawSqu(g);
            drawCircle(g);
            drawHeart(g);
            p.shield(g, dir);
            gif(g);
            try {
                a1.spawnArrows(g, p);
                p.drawHealth(g);
            }
            catch (FontFormatException | IOException e) {
                e.printStackTrace();
            }
        }
        else {
            drawBG(g);
            if(firstEnd) {
                Sound.stopGroup(mainSound);
                firstEnd = false;
            }
            if(!heartDone)
                breakHeart(g);
            else if(secondEnd){
                secondEnd = false;
                ArrayList<Sound> determination = new ArrayList<Sound>();
                try {
                    for(int i = 1; i <= 6; ++i) {
                        determination.add(new Sound("audio/DT" + i + ".wav", false));
                    }
                    Sound.playGroup(determination, true);
                }
                catch(Exception e) {
                    e.printStackTrace();
                }
            }
            else if(!gameOverDone){
                gameOver(g);
            }
        }
    }

    public boolean breakHeartException(int breakFrame) {
        int[] exceptions = {2, 6, 8, 12, 14, 18, 20, 22, 23};
        for(int exception : exceptions) {
            if(breakFrame == exception)
                return true;
        }
        return false;
    }

    public void makeBreakHeart(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        int width = heartBreak.getWidth();
        int height = heartBreak.getHeight();
        g2d.drawImage(heartBreak, getWidth() / 2 - (width / 2) + 11, getHeight() / 2 - height / 2 + 78, null);
        g2d.dispose();
    }

    public void breakHeart(Graphics g) {
        ++breakCount;
        boolean exception = breakHeartException(breakFrame);
        try {
            heartBreak = ImageIO.read(new File("images/gif/heartBreak" + breakFrame + ".png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(breakCount % 4 == 0 && breakCount != 0 && !exception) {
            ++breakFrame;
            if(breakFrame == 25) {
                try {
                    Sound split = new Sound("audio/split.wav", false);
                    split.play();
                } catch (IOException | UnsupportedAudioFileException e) {
                    e.printStackTrace();
                }
            }
            if(breakFrame == 48)
                heartDone = true;
            breakCount = 0;
        }
        else if(exception) {
            switch(breakFrame) {
                case 2:
                case 12:
                    if(breakCount % 24 == 0) {
                        ++breakFrame;
                        breakCount = 0;
                    }
                    break;
                case 14:
                    if(breakCount % 28 == 0) {
                        ++breakFrame;
                        breakCount = 0;
                    }
                    break;
                default:
                    if(breakCount % 8 == 0) {
                        ++breakFrame;
                        if(breakFrame == 9) {
                            try {
                                Sound broke = new Sound("audio/heartBreak.wav", false);
                                broke.play();
                            } catch (IOException | UnsupportedAudioFileException e) {
                                e.printStackTrace();
                            }
                        }
                        breakCount = 0;
                    }
            }
        }
        makeBreakHeart(g);
    }

    public void gameOver(Graphics g) {
        ++gameOverCount;
        try {
            gameOver = ImageIO.read(new File("images/gif/gameOver" + gameOverFrame + ".png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        if(gameOverCount % 4 == 0 && gameOverCount != 0) {
            ++gameOverFrame;
            switch(gameOverFrame) {
                case 68:
                case 70:
                case 73:
                case 75:
                case 76:
                case 78:
                case 80:
                case 81:
                case 85:
                case 86:
                case 88:
                case 93:
                case 95:
                case 96:
                case 98:
                    try {
                        Sound asgore = new Sound("audio/asgore.wav", false);
                        asgore.play();
                    }
                    catch(Exception e) {
                        e.printStackTrace();
                    }
                    break;
            }
            if(gameOverFrame == 225)
                gameOverDone = true;
            gameOverCount = 0;
        }
        Graphics2D g2d = (Graphics2D) g.create();
        int width = gameOver.getWidth();
        int height = gameOver.getHeight();
        g2d.drawImage(gameOver, getWidth() / 2 - (width / 2) + 1, getHeight() / 2 - height / 2, null);
        g2d.dispose();
    }

    @Override
    public void actionPerformed(ActionEvent e) { 
        repaint();
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    @Override
    public void keyPressed(KeyEvent e) {
        switch (e.getKeyCode()) {
        case KeyEvent.VK_UP:
            dir = 'u';
            break;
        case KeyEvent.VK_DOWN:
            dir = 'd';
            break;
        case KeyEvent.VK_RIGHT:
            dir = 'r';
            break;
        case KeyEvent.VK_LEFT:
            dir = 'l';
            break;
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }
}