Exoplayer: MP3 to PCM decoding

Created on 21 Jan 2019  路  9Comments  路  Source: google/ExoPlayer

Is it possible to decode mp3 file to pcm raw data using exoplayer library and play it via android.media.AudioTrack?

question

Most helpful comment

When calling ExoPlayerFactory.newSimpleInstance you can pass a RenderersFactory. DefaultRenderersFactory lets you specify AudioProcessors. Here is a basic example that just dumps audio data to logs:

new DefaultRenderersFactory(/* context= */ this) {
  @Override
  protected AudioProcessor[] buildAudioProcessors() {
    return new AudioProcessor[] {new TeeAudioProcessor(new TeeAudioProcessor.AudioBufferSink() {
      @Override
      public void flush(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding) {
        Log.w("DEBUG", "PCM configuration: sampleRateHz=" + sampleRateHz + ", channelCount=" + channelCount + ", encoding=" + encoding);
      }

      @Override
      public void handleBuffer(ByteBuffer buffer) {
        StringBuilder sb = new StringBuilder();
        while (buffer.hasRemaining()) {
          sb.append(String.format("%02x", buffer.get()));
        }
        Log.w("DEBUG", "PCM data: " + sb);
      }
    })};
  }
}

All 9 comments

That's what ExoPlayer does if you just use it to play an MP3.

That's what ExoPlayer does if you just use it to play an MP3.

But how I can decode it myself?

It's unclear what you're actually trying to do. ExoPlayer does exactly what your initial question asks automatically. Perhaps try and describe what you want in more detail. Thanks.

All I need is just decode mp3 to pcm. For example, there is JLayer library, that can solve this problem. So the question is "can exoplayer library be used to decode mp3 to pcm and give stream of decoded data for future usage?". Thanks

The library contains all the pieces you'd need to do this, but not in a form that makes it particularly easy to wire everything up. @andrewlewis might be able to provide some rough guidance, but this isn't really a use case we're trying to support.

You can control how decoded PCM audio is handled by replacing DefaultAudioSink (which writes to a platform AudioTrack) with your own implementation of AudioSink. You can inject this custom sink when constructing MediaCodecAudioRenderer in your RenderersFactory.

Alternatively, if you don't mind having ExoPlayer write the data to an AudioTrack that you can mute, you can continue to use DefaultAudioSink but pass in a TeeAudioProcessor via RenderersFactory.buildAudioProcessors. Then you'd implement the much simpler TeeAudioProcessor.AudioBufferSink API to handle the audio samples that are getting written to the AudioTrack. With this approach you don't get to control the player's position (media clock), however.

Thanks for suggestions!

Hey @andrewlewis, sorry for asking this, but I'm new with ExoPlayer. Can you provide any example on how "pass in a TeeAudioProcessor via RenderersFactory.buildAudioProcessors". I searched on Google, but didn't found nothing.

I appreciate, thank you very much.

When calling ExoPlayerFactory.newSimpleInstance you can pass a RenderersFactory. DefaultRenderersFactory lets you specify AudioProcessors. Here is a basic example that just dumps audio data to logs:

new DefaultRenderersFactory(/* context= */ this) {
  @Override
  protected AudioProcessor[] buildAudioProcessors() {
    return new AudioProcessor[] {new TeeAudioProcessor(new TeeAudioProcessor.AudioBufferSink() {
      @Override
      public void flush(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding) {
        Log.w("DEBUG", "PCM configuration: sampleRateHz=" + sampleRateHz + ", channelCount=" + channelCount + ", encoding=" + encoding);
      }

      @Override
      public void handleBuffer(ByteBuffer buffer) {
        StringBuilder sb = new StringBuilder();
        while (buffer.hasRemaining()) {
          sb.append(String.format("%02x", buffer.get()));
        }
        Log.w("DEBUG", "PCM data: " + sb);
      }
    })};
  }
}
Was this page helpful?
0 / 5 - 0 ratings