歌曲第一次播放,但一旦停止播放,不播放:用Java剪辑

Pro*_*mer 3 java audio clip

我在Java中使用Clip来播放如下歌曲:

        MR.clip= (Clip) AudioSystem.getLine(MR.info[docIdOfSelectedSong]);
        MR.clip.open(MR.sounds[docIdOfSelectedSong]);
        MR.clip.setMicrosecondPosition(5* 1000000);
        MR.clip.start();
Run Code Online (Sandbox Code Playgroud)

其中MR.sounds是一个类型的数组,AudioInputStreamMR.info是一个类型的数组DataLine.info.当我按下按钮时,上面的代码被调用来播放歌曲.此外,我有另一个按钮来停止调用以下代码的歌曲

public static void stopSong(){

    MR.clip.close();

}
Run Code Online (Sandbox Code Playgroud)

问题是,当我第一次播放歌曲时,播放和停止按钮工作正常.但是,当我第二次尝试播放这首歌时,我听不到这首歌.什么是错误的任何建议?

Mik*_*ark 6

与所有其他InputStream一样,AudioInputStream只能读取一次(除非它可以是.reset()).在尝试再次播放声音之前,您可以尝试在AudioInputStream上调用.reset(),但AudioInputStream可能不支持.reset().InputStreams不需要支持重置.另请参见markSupported().

如果.reset()不起作用,请考虑每次需要开始播放时构建一个新的AudioInputStream.


更新:我做了一个在内存中缓存声音数据并使用Clip播放这些声音的示例.此示例使用AudioInputStream.reset().那怎么可行呢?实际上,的AudioInputStream 支撑重置()当且仅当其底层InputStream支持.reset段().所以我的示例创建了一个由ByteArrayInputStream支持的AudioInputStream.因为ByteArrayInputStream支持重置,所以这些缓存的AudioInputStreams也支持.reset(),允许重用它们.

请注意,如果您要同时播放任何一种缓存声音,则可能不应缓存AudioInputStreams,而是缓存byte[]并构建AudioInputStream每次播放.这是因为AudioInputStream是有状态的,因此将其单个实例传递给两个同时运行的剪辑,或者在播放一个剪辑时重置流将导致状态冲突.

public class CachedSoundClipTest
{
    static ArrayList<AudioInputStream> cachedSounds = 
        new ArrayList<AudioInputStream>();

    public static void main(String[] args) throws Exception
    {
        File[] audioFiles = new File("/audio_storage_directory").listFiles();
        for (File file : audioFiles)
        {
            AudioInputStream reusableAudioInputStream = 
                createReusableAudioInputStream(file);
            cachedSounds.add(reusableAudioInputStream);
        }

        while(true)
        {
            System.out.println("Press enter to play next clip");
            BufferedReader br = 
                new BufferedReader(new InputStreamReader(System.in));
            br.readLine();
            playCachedSound(0);
        }
    }

    private static void playCachedSound(int i) 
        throws IOException, LineUnavailableException
    {
        AudioInputStream stream = cachedSounds.get(i);
        stream.reset();
        Clip clip = AudioSystem.getClip();
        clip.open(stream);
        clip.start();
    }

    private static AudioInputStream createReusableAudioInputStream(File file) 
        throws IOException, UnsupportedAudioFileException
    {
        AudioInputStream ais = null;
        try
        {
            ais = AudioSystem.getAudioInputStream(file);
            byte[] buffer = new byte[1024 * 32];
            int read = 0;
            ByteArrayOutputStream baos = 
                new ByteArrayOutputStream(buffer.length);
            while ((read = ais.read(buffer, 0, buffer.length)) != -1)
            {
                baos.write(buffer, 0, read);
            }
            AudioInputStream reusableAis = 
                new AudioInputStream(
                        new ByteArrayInputStream(baos.toByteArray()),
                        ais.getFormat(),
                        AudioSystem.NOT_SPECIFIED);
            return reusableAis;
        }
        finally
        {
            if (ais != null)
            {
                ais.close();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Tho*_*mas 6

诀窍是将剪辑的当前位置重置为开始.

clip.stop();
clip.setMicrosecondPosition(0);
clip.start();
Run Code Online (Sandbox Code Playgroud)

使用此方法,不必多次加载相同的资源.剪辑应仅加载一次并存储为实例变量或其他内容.