Add support for AudioTrack pitch/speed alteration on API 23.

Issue #26
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=108958826
This commit is contained in:
aquilescanta 2015-11-30 02:20:24 -08:00 committed by Andrew Lewis
parent 33506adab5
commit 6570ef0e48
2 changed files with 87 additions and 7 deletions

View file

@ -24,6 +24,7 @@ import com.google.android.exoplayer.util.MimeTypes;
import android.annotation.TargetApi;
import android.media.AudioManager;
import android.media.MediaCodec;
import android.media.PlaybackParams;
import android.media.audiofx.Virtualizer;
import android.os.Handler;
import android.os.SystemClock;
@ -76,6 +77,14 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
*/
public static final int MSG_SET_VOLUME = 1;
/**
* The type of a message that can be passed to an instance of this class via
* {@link ExoPlayer#sendMessage} or {@link ExoPlayer#blockingSendMessage}. The message object
* should be a {@link android.media.PlaybackParams}. This will be used to configure the
* underlying {@link android.media.AudioTrack}.
*/
public static final int MSG_SET_PLAYBACK_PARAMS = 2;
/**
* The name for the raw (passthrough) decoder OMX component.
*/
@ -401,10 +410,16 @@ public class MediaCodecAudioTrackRenderer extends MediaCodecTrackRenderer implem
@Override
public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
if (messageType == MSG_SET_VOLUME) {
audioTrack.setVolume((Float) message);
} else {
super.handleMessage(messageType, message);
switch (messageType) {
case MSG_SET_VOLUME:
audioTrack.setVolume((Float) message);
break;
case MSG_SET_PLAYBACK_PARAMS:
audioTrack.setPlaybackParams((PlaybackParams) message);
break;
default:
super.handleMessage(messageType, message);
break;
}
}

View file

@ -26,6 +26,7 @@ import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTimestamp;
import android.media.MediaFormat;
import android.media.PlaybackParams;
import android.os.ConditionVariable;
import android.os.SystemClock;
import android.util.Log;
@ -248,7 +249,9 @@ public final class AudioTrack {
// There's no guarantee this method exists. Do nothing.
}
}
if (Util.SDK_INT >= 19) {
if (Util.SDK_INT >= 23) {
audioTrackUtil = new AudioTrackUtilV23();
} else if (Util.SDK_INT >= 19) {
audioTrackUtil = new AudioTrackUtilV19();
} else {
audioTrackUtil = new AudioTrackUtil();
@ -300,7 +303,10 @@ public final class AudioTrack {
if (audioTimestampSet) {
// How long ago in the past the audio timestamp is (negative if it's in the future).
long presentationDiff = systemClockUs - (audioTrackUtil.getTimestampNanoTime() / 1000);
long framesDiff = durationUsToFrames(presentationDiff);
// Fixes such difference if the playback speed is not real time speed.
long actualSpeedPresentationDiff = (long) (presentationDiff
* audioTrackUtil.getPlaybackSpeed());
long framesDiff = durationUsToFrames(actualSpeedPresentationDiff);
// The position of the frame that's currently being presented.
long currentFramePosition = audioTrackUtil.getTimestampFramePosition() + framesDiff;
currentPositionUs = framesToDurationUs(currentFramePosition) + startMediaTimeUs;
@ -652,9 +658,20 @@ public final class AudioTrack {
public boolean hasPendingData() {
return isInitialized()
&& (getSubmittedFrames() > audioTrackUtil.getPlaybackHeadPosition()
|| overrideHasPendingData());
|| overrideHasPendingData());
}
/**
* Sets the playback parameters. Only available for SDK_INT >= 23
*
* @throws UnsupportedOperationException if the Playback Parameters are not supported. That is,
* SDK_INT < 23.
*/
public void setPlaybackParams(PlaybackParams playbackParams) {
audioTrackUtil.setPlaybackParameters(playbackParams);
}
/**
* Sets the playback volume.
*/
@ -1100,6 +1117,27 @@ public final class AudioTrack {
throw new UnsupportedOperationException();
}
/**
* Sets the Playback Parameters to be used by the underlying {@link android.media.AudioTrack}.
*
* @param playbackParams to be used by the {@link android.media.AudioTrack}.
* @throws UnsupportedOperationException If Playback Parameters are not supported
* (i.e. SDK_INT < 23).
*/
public void setPlaybackParameters(PlaybackParams playbackParams) {
throw new UnsupportedOperationException();
}
/**
* Returns the configured playback speed according to the used Playback Parameters. If these are
* not supported, 1.0f(normal speed) is returned.
*
* @return The speed factor used by the underlying {@link android.media.AudioTrack}.
*/
public float getPlaybackSpeed() {
return 1.0f;
}
}
@TargetApi(19)
@ -1151,4 +1189,31 @@ public final class AudioTrack {
}
@TargetApi(23)
private static class AudioTrackUtilV23 extends AudioTrackUtilV19 {
private PlaybackParams playbackParams;
@Override
public void reconfigure(android.media.AudioTrack audioTrack,
boolean needsPassthroughWorkaround) {
super.reconfigure(audioTrack, needsPassthroughWorkaround);
setPlaybackParameters(playbackParams);
}
public void setPlaybackParameters(PlaybackParams playbackParams) {
this.playbackParams = playbackParams;
if (audioTrack != null && playbackParams != null) {
audioTrack.setPlaybackParams(playbackParams);
}
}
public float getPlaybackSpeed() {
if (playbackParams != null) {
return playbackParams.getSpeed();
} else {
return 1.0f;
}
}
}
}