简体   繁体   English

使用JLayer播放MP3时以毫秒为单位指定开始/停止时间

[英]Specifying start/stop time in millisecs when playing MP3 using JLayer

I need to play a part of an MP3 file in my java code. 我需要在我的Java代码中播放MP3文件的一部分。 I wish to do this via a function which accepts the start and stop time in millisecs. 我希望通过一个以毫秒为单位接受开始和结束时间的函数来完成此操作。

JLayer contains a class called AdvancedPlayer which has a method that accepts the start and stop position in frames: JLayer包含一个名为AdvancedPlayer的类,该类具有一个接受帧中开始和停止位置的方法:

/**
 * Plays a range of MPEG audio frames
 * @param start The first frame to play
 * @param end       The last frame to play 
 * @return true if the last frame was played, or false if there are more frames.
 */
public boolean play(final int start, final int end) throws JavaLayerException
{
    boolean ret = true;
    int offset = start;
    while (offset-- > 0 && ret) ret = skipFrame();
    return play(end - start);
}

According to this , a frame lasts 26millisecs. 根据这个 ,一帧持续26millisecs。 However I need a finer degree of control than this, ie I may wish to play from 40millisecs to 50millisecs. 但是我需要比这更好的控制度,即我可能希望从40毫米玩到50毫米玩。

How can I do this? 我怎样才能做到这一点? Do I need to convert the MP3 to .wav first? 我需要先将MP3转换为.wav吗?

The solution I used in the end was to first write the code to play a part of a wave file (ie from xxx ms to xxx ms) as I also need support for this file format. 最后,我使用的解决方案是首先编写代码以播放wave文件的一部分(即,从xxx毫秒到xxx毫秒),因为我也需要对此文件格式的支持。 Here's the code for that: 这是该代码:

File soundFile = new File(this.audioFilePath);
AudioInputStream originalAudioInputStream = AudioSystem.getAudioInputStream(soundFile);
AudioFormat audioFormat = originalAudioInputStream.getFormat();

float startInBytes = (startTimeinMs / 1000 * audioFormat.getSampleRate() * audioFormat.getFrameSize());
float lengthInFrames = ((endTimeinMs - startTimeinMs) / 1000 * audioFormat.getSampleRate());

originalAudioInputStream.skip((long) startInBytes);
AudioInputStream partAudioInputStream = new AudioInputStream(originalAudioInputStream,
                originalAudioInputStream.getFormat(), (long) lengthInFrames);

// code to actually play the audio input stream here

Once this was working I wrote this code to convert an MP3 to a temporary wave file (which I can then use with the above code) - this is using JLayer and MP3SPI. 一旦工作成功,我就编写了这段代码将MP3转换为临时wave文件(然后可以与上面的代码一起使用)-这是使用JLayer和MP3SPI。 I did try simply performing the above directly on the converted audio stream without first writing out to a file but couldn't get it to work. 我确实尝试了直接在转换后的音频流上直接执行上述操作,而没有先写出文件,但无法使其正常工作。 I'm only using small MP3 files that convert/write out instantly so I'm happy with this solution. 我只使用可立即转换/写出的小型MP3文件,因此对此解决方案感到满意。

File soundFile = new File(this.inputFilePath);
AudioInputStream mp3InputStream = AudioSystem.getAudioInputStream(soundFile);
AudioFormat baseFormat = mp3InputStream.getFormat();
AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,  baseFormat.getSampleRate(),  16, baseFormat.getChannels(), baseFormat.getChannels() * 2,  baseFormat.getSampleRate(), false);

AudioInputStream convertedAudioInputStream =  AudioSystem.getAudioInputStream(decodedFormat, mp3InputStream);

File outputFile = new File(this.outputFilePath);
AudioSystem.write(convertedAudioInputStream, AudioFileFormat.Type.WAVE, outputFile);

If 26 milliseconds is the finest resolution you can achieve in an MP3 file, then you're out of luck. 如果26毫秒是您在MP3文件中可以达到的最佳分辨率,那么您就不走运了。 Converting it to WAV might work, but the source data (ie the MP3) stil has that basic resolution limit. 将其转换为WAV可能可行,但是源数据(即MP3)stil具有该基本分辨率限制。

Out of curiosity, why do you want to play 10 milliseconds worth of audio? 出于好奇,您为什么要播放价值10毫秒的音频?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM