首页 > 解决方案 > 是否有可能以某种方式将 .setMicrosecondPosition() 与线一起使用,还是只能与剪辑一起使用

问题描述

我目前正在制作 mp3 播放器,NetBeans 12.1但找不到控制歌曲当前位置的方法。

我试过使用.setMicrosecondPosition(),但它似乎只适用于剪辑而不适用于线。我的播放器甚至可以更改曲目的当前位置还是我应该更改我的代码?

这是播放器的代码。

public void run() {
        final File file = new File(filePath);
        try (final AudioInputStream in = AudioSystem.getAudioInputStream(file)) {
            final AudioFormat outFormat = getOutFormat(in.getFormat());
            final Info info = new Info(SourceDataLine.class, outFormat);

            try (final SourceDataLine line
                    = (SourceDataLine) AudioSystem.getLine(info)) {
                getLine(line);
                line.getMicrosecondPosition();
                if (line != null) {
                    line.open(outFormat);
                    line.start();
  
                    long millis;
                    AudioFileFormat fileFormat = AudioSystem.getAudioFileFormat(file);
                    Map<?, ?> properties = ((TAudioFileFormat) fileFormat).properties();
                    String key = "duration";
                    String title = "title";
                    Long microseconds = (Long) properties.get(key);
                    maksimumSekunde = (int)TimeUnit.MICROSECONDS.toSeconds(microseconds);
                    title1 = (String) properties.get(title);
                    int mili = (int) (microseconds / 1000);
                    sec = (mili / 1000) % 60;
                    min = (mili / 1000) / 60;

                    setVolumeDown(sliderGlasnoca.getValue());
                    //STREAM
                    int n = 0;
                    final byte[] buffer = new byte[4096];
                    AudioInputStream inp = getAudioInputStream(outFormat, in);

                    while (n != -1) {
                        if (pauza == true) {
                            break;
                        }
                        if (stop == true) {
                            synchronized (LOCK) {
                                LOCK.wait();
                            }

                        }
                        n = inp.read(buffer, 0, buffer.length);
                        if (n != -1) {
                            line.write(buffer, 0, n);
                        }
                        millis = TimeUnit.MICROSECONDS.toMillis(line.getMicrosecondPosition());
                        trajanjeSekunde = (int)TimeUnit.MICROSECONDS.toSeconds(line.getMicrosecondPosition());
                        minutes = (millis / 1000) / 60;
                        seconds = ((millis / 1000) % 60);

                        //System.out.println(minutes + ":" + seconds + " " + "time = " + min + ":" + sec + " " + title1);
                    }
                    //STREAM
                    line.drain();
                    line.stop();
                    Finished();
                }
            } catch (InterruptedException ex) {

            }

        } catch (UnsupportedAudioFileException
                | LineUnavailableException
                | IOException e) {
            throw new IllegalStateException(e);
        }
    }

这是我第一次在这里发帖。

标签: javaaudio

解决方案


我总是从通过 读取的字节中计数和丢弃帧AudioInputStream,但重新审视 API,我发现可以使用该AudioInputStream.skip(...)方法向前跳转给定数量的字节。计算对应于给定时间量的字节数涉及知道每帧的字节数,例如,16 位编码,立体声是每帧 4 字节,以及采样率。

IDK 如果一个人可以可靠地向后跳过。这将取决于是否可以“标记”和“重置” AudioInputStream. 如果支持这些功能,似乎可以想象mark(...). AudioInputStream然后,要向后退,首先reset()回到起点,然后通过 向前跳skip(...)。我没有测试过这个。很大程度上取决于mark(...)方法中允许的字节数。

如果在播放音频的中间开始或停止,由于信号的不连续性,馈送到的数据SourceDataLine可能会出现“咔哒”声。为了解决这个问题,可能需要将启动和停止转换为 PCM,并在启动时提高音量,或者在停止时降低音量。所需的帧数可能需要通过实验来确定。我猜 44100fps 的 64 帧可能是一个不错的第一次尝试。


推荐阅读