views:

594

answers:

2

I need to play a part of an MP3 file in my java code. 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:

/**
 * 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. However I need a finer degree of control than this, i.e. I may wish to play from 40millisecs to 50millisecs.

How can I do this? Do I need to convert the MP3 to .wav first?

A: 

If 26 milliseconds is the finest resolution you can achieve in an MP3 file, then you're out of luck. Converting it to WAV might work, but the source data (i.e. the MP3) stil has that basic resolution limit.

Out of curiosity, why do you want to play 10 milliseconds worth of audio?

skaffman
A: 

The solution I used in the end was to first write the code to play a part of a wave file (i.e. from xxx ms to xxx ms) as I also need support for this file format. 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. 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.

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);
William