mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-23 16:40:32 +00:00
Major refactoring of PlaybackParameterDialog
* Removed/Renamed methods * Use ``IcePick`` * Better structuring * Keep skipSilence when rotating the device (PlayQueueActivity only)
This commit is contained in:
parent
6e81f2430b
commit
652d50173e
@ -9,10 +9,10 @@ import android.os.Bundle;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.RelativeLayout;
|
|
||||||
import android.widget.SeekBar;
|
import android.widget.SeekBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.IdRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
@ -20,104 +20,88 @@ import androidx.fragment.app.DialogFragment;
|
|||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.util.SimpleOnSeekBarChangeListener;
|
|
||||||
import org.schabi.newpipe.util.SliderStrategy;
|
import org.schabi.newpipe.util.SliderStrategy;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.DoubleConsumer;
|
||||||
|
import java.util.function.DoubleFunction;
|
||||||
|
|
||||||
|
import icepick.Icepick;
|
||||||
|
import icepick.State;
|
||||||
|
|
||||||
public class PlaybackParameterDialog extends DialogFragment {
|
public class PlaybackParameterDialog extends DialogFragment {
|
||||||
|
private static final String TAG = "PlaybackParameterDialog";
|
||||||
|
|
||||||
// Minimum allowable range in ExoPlayer
|
// Minimum allowable range in ExoPlayer
|
||||||
private static final double MINIMUM_PLAYBACK_VALUE = 0.10f;
|
private static final double MINIMUM_PLAYBACK_VALUE = 0.10f;
|
||||||
private static final double MAXIMUM_PLAYBACK_VALUE = 3.00f;
|
private static final double MAXIMUM_PLAYBACK_VALUE = 3.00f;
|
||||||
|
|
||||||
private static final char STEP_UP_SIGN = '+';
|
private static final double STEP_1_PERCENT_VALUE = 0.01f;
|
||||||
private static final char STEP_DOWN_SIGN = '-';
|
private static final double STEP_5_PERCENT_VALUE = 0.05f;
|
||||||
|
private static final double STEP_10_PERCENT_VALUE = 0.10f;
|
||||||
private static final double STEP_ONE_PERCENT_VALUE = 0.01f;
|
private static final double STEP_25_PERCENT_VALUE = 0.25f;
|
||||||
private static final double STEP_FIVE_PERCENT_VALUE = 0.05f;
|
private static final double STEP_100_PERCENT_VALUE = 1.00f;
|
||||||
private static final double STEP_TEN_PERCENT_VALUE = 0.10f;
|
|
||||||
private static final double STEP_TWENTY_FIVE_PERCENT_VALUE = 0.25f;
|
|
||||||
private static final double STEP_ONE_HUNDRED_PERCENT_VALUE = 1.00f;
|
|
||||||
|
|
||||||
private static final double DEFAULT_TEMPO = 1.00f;
|
private static final double DEFAULT_TEMPO = 1.00f;
|
||||||
private static final double DEFAULT_PITCH = 1.00f;
|
private static final double DEFAULT_PITCH = 1.00f;
|
||||||
private static final int DEFAULT_SEMITONES = 0;
|
private static final double DEFAULT_STEP = STEP_25_PERCENT_VALUE;
|
||||||
private static final double DEFAULT_STEP = STEP_TWENTY_FIVE_PERCENT_VALUE;
|
|
||||||
private static final boolean DEFAULT_SKIP_SILENCE = false;
|
private static final boolean DEFAULT_SKIP_SILENCE = false;
|
||||||
|
|
||||||
@NonNull
|
private static final SliderStrategy QUADRATIC_STRATEGY = new SliderStrategy.Quadratic(
|
||||||
private static final String TAG = "PlaybackParameterDialog";
|
MINIMUM_PLAYBACK_VALUE,
|
||||||
@NonNull
|
MAXIMUM_PLAYBACK_VALUE,
|
||||||
private static final String INITIAL_TEMPO_KEY = "initial_tempo_key";
|
1.00f,
|
||||||
@NonNull
|
10_000);
|
||||||
private static final String INITIAL_PITCH_KEY = "initial_pitch_key";
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private static final String TEMPO_KEY = "tempo_key";
|
|
||||||
@NonNull
|
|
||||||
private static final String PITCH_KEY = "pitch_key";
|
|
||||||
@NonNull
|
|
||||||
private static final String STEP_SIZE_KEY = "step_size_key";
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private final SliderStrategy strategy = new SliderStrategy.Quadratic(
|
|
||||||
MINIMUM_PLAYBACK_VALUE, MAXIMUM_PLAYBACK_VALUE,
|
|
||||||
/*centerAt=*/1.00f, /*sliderGranularity=*/10000);
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
|
|
||||||
private double initialTempo = DEFAULT_TEMPO;
|
@State
|
||||||
private double initialPitch = DEFAULT_PITCH;
|
double initialTempo = DEFAULT_TEMPO;
|
||||||
private int initialSemitones = DEFAULT_SEMITONES;
|
@State
|
||||||
private boolean initialSkipSilence = DEFAULT_SKIP_SILENCE;
|
double initialPitch = DEFAULT_PITCH;
|
||||||
private double tempo = DEFAULT_TEMPO;
|
@State
|
||||||
private double pitch = DEFAULT_PITCH;
|
boolean initialSkipSilence = DEFAULT_SKIP_SILENCE;
|
||||||
private int semitones = DEFAULT_SEMITONES;
|
|
||||||
|
@State
|
||||||
|
double tempo = DEFAULT_TEMPO;
|
||||||
|
@State
|
||||||
|
double pitch = DEFAULT_PITCH;
|
||||||
|
@State
|
||||||
|
double stepSize = DEFAULT_STEP;
|
||||||
|
@State
|
||||||
|
boolean skipSilence = DEFAULT_SKIP_SILENCE;
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private SeekBar tempoSlider;
|
private SeekBar tempoSlider;
|
||||||
@Nullable
|
|
||||||
private TextView tempoCurrentText;
|
private TextView tempoCurrentText;
|
||||||
@Nullable
|
|
||||||
private TextView tempoStepDownText;
|
private TextView tempoStepDownText;
|
||||||
@Nullable
|
|
||||||
private TextView tempoStepUpText;
|
private TextView tempoStepUpText;
|
||||||
@Nullable
|
|
||||||
private SeekBar pitchSlider;
|
|
||||||
@Nullable
|
|
||||||
private TextView pitchCurrentText;
|
|
||||||
@Nullable
|
|
||||||
private TextView pitchStepDownText;
|
|
||||||
@Nullable
|
|
||||||
private TextView pitchStepUpText;
|
|
||||||
@Nullable
|
|
||||||
private SeekBar semitoneSlider;
|
|
||||||
@Nullable
|
|
||||||
private TextView semitoneCurrentText;
|
|
||||||
@Nullable
|
|
||||||
private TextView semitoneStepDownText;
|
|
||||||
@Nullable
|
|
||||||
private TextView semitoneStepUpText;
|
|
||||||
@Nullable
|
|
||||||
private CheckBox unhookingCheckbox;
|
|
||||||
@Nullable
|
|
||||||
private CheckBox skipSilenceCheckbox;
|
|
||||||
@Nullable
|
|
||||||
private CheckBox adjustBySemitonesCheckbox;
|
|
||||||
|
|
||||||
public static PlaybackParameterDialog newInstance(final double playbackTempo,
|
private SeekBar pitchSlider;
|
||||||
|
private TextView pitchCurrentText;
|
||||||
|
private TextView pitchStepDownText;
|
||||||
|
private TextView pitchStepUpText;
|
||||||
|
|
||||||
|
private CheckBox unhookingCheckbox;
|
||||||
|
private CheckBox skipSilenceCheckbox;
|
||||||
|
|
||||||
|
public static PlaybackParameterDialog newInstance(
|
||||||
|
final double playbackTempo,
|
||||||
final double playbackPitch,
|
final double playbackPitch,
|
||||||
final boolean playbackSkipSilence,
|
final boolean playbackSkipSilence,
|
||||||
final Callback callback) {
|
final Callback callback
|
||||||
|
) {
|
||||||
final PlaybackParameterDialog dialog = new PlaybackParameterDialog();
|
final PlaybackParameterDialog dialog = new PlaybackParameterDialog();
|
||||||
dialog.callback = callback;
|
dialog.callback = callback;
|
||||||
|
|
||||||
dialog.initialTempo = playbackTempo;
|
dialog.initialTempo = playbackTempo;
|
||||||
dialog.initialPitch = playbackPitch;
|
dialog.initialPitch = playbackPitch;
|
||||||
|
|
||||||
dialog.tempo = playbackTempo;
|
|
||||||
dialog.pitch = playbackPitch;
|
|
||||||
dialog.semitones = dialog.percentToSemitones(playbackPitch);
|
|
||||||
|
|
||||||
dialog.initialSkipSilence = playbackSkipSilence;
|
dialog.initialSkipSilence = playbackSkipSilence;
|
||||||
|
|
||||||
|
dialog.tempo = dialog.initialTempo;
|
||||||
|
dialog.pitch = dialog.initialPitch;
|
||||||
|
dialog.skipSilence = dialog.initialSkipSilence;
|
||||||
|
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +110,7 @@ public class PlaybackParameterDialog extends DialogFragment {
|
|||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAttach(@NonNull final Context context) {
|
public void onAttach(final Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
if (context instanceof Callback) {
|
if (context instanceof Callback) {
|
||||||
callback = (Callback) context;
|
callback = (Callback) context;
|
||||||
@ -136,28 +120,9 @@ public class PlaybackParameterDialog extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
public void onSaveInstanceState(final Bundle outState) {
|
||||||
assureCorrectAppLanguage(getContext());
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
if (savedInstanceState != null) {
|
|
||||||
initialTempo = savedInstanceState.getDouble(INITIAL_TEMPO_KEY, DEFAULT_TEMPO);
|
|
||||||
initialPitch = savedInstanceState.getDouble(INITIAL_PITCH_KEY, DEFAULT_PITCH);
|
|
||||||
initialSemitones = percentToSemitones(initialPitch);
|
|
||||||
|
|
||||||
tempo = savedInstanceState.getDouble(TEMPO_KEY, DEFAULT_TEMPO);
|
|
||||||
pitch = savedInstanceState.getDouble(PITCH_KEY, DEFAULT_PITCH);
|
|
||||||
semitones = percentToSemitones(pitch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSaveInstanceState(@NonNull final Bundle outState) {
|
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
outState.putDouble(INITIAL_TEMPO_KEY, initialTempo);
|
Icepick.saveInstanceState(this, outState);
|
||||||
outState.putDouble(INITIAL_PITCH_KEY, initialPitch);
|
|
||||||
|
|
||||||
outState.putDouble(TEMPO_KEY, getCurrentTempo());
|
|
||||||
outState.putDouble(PITCH_KEY, getCurrentPitch());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
@ -168,20 +133,28 @@ public class PlaybackParameterDialog extends DialogFragment {
|
|||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
|
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
|
||||||
assureCorrectAppLanguage(getContext());
|
assureCorrectAppLanguage(getContext());
|
||||||
|
Icepick.restoreInstanceState(this, savedInstanceState);
|
||||||
|
|
||||||
final View view = View.inflate(getContext(), R.layout.dialog_playback_parameter, null);
|
final View view = View.inflate(getContext(), R.layout.dialog_playback_parameter, null);
|
||||||
setupControlViews(view);
|
initUI(view);
|
||||||
|
initUIData();
|
||||||
|
|
||||||
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(requireActivity())
|
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(requireActivity())
|
||||||
.setView(view)
|
.setView(view)
|
||||||
.setCancelable(true)
|
.setCancelable(true)
|
||||||
.setNegativeButton(R.string.cancel, (dialogInterface, i) ->
|
.setNegativeButton(R.string.cancel, (dialogInterface, i) -> {
|
||||||
setPlaybackParameters(initialTempo, initialPitch,
|
setAndUpdateTempo(initialTempo);
|
||||||
initialSemitones, initialSkipSilence))
|
setAndUpdatePitch(initialPitch);
|
||||||
.setNeutralButton(R.string.playback_reset, (dialogInterface, i) ->
|
setAndUpdateSkipSilence(initialSkipSilence);
|
||||||
setPlaybackParameters(DEFAULT_TEMPO, DEFAULT_PITCH,
|
updateCallback();
|
||||||
DEFAULT_SEMITONES, DEFAULT_SKIP_SILENCE))
|
})
|
||||||
.setPositiveButton(R.string.ok, (dialogInterface, i) ->
|
.setNeutralButton(R.string.playback_reset, (dialogInterface, i) -> {
|
||||||
setCurrentPlaybackParameters());
|
setAndUpdateTempo(DEFAULT_TEMPO);
|
||||||
|
setAndUpdatePitch(DEFAULT_PITCH);
|
||||||
|
setAndUpdateSkipSilence(DEFAULT_SKIP_SILENCE);
|
||||||
|
updateCallback();
|
||||||
|
})
|
||||||
|
.setPositiveButton(R.string.ok, (dialogInterface, i) -> updateCallback());
|
||||||
|
|
||||||
return dialogBuilder.create();
|
return dialogBuilder.create();
|
||||||
}
|
}
|
||||||
@ -190,353 +163,171 @@ public class PlaybackParameterDialog extends DialogFragment {
|
|||||||
// Control Views
|
// Control Views
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
private void setupControlViews(@NonNull final View rootView) {
|
private void initUI(@NonNull final View rootView) {
|
||||||
setupHookingControl(rootView);
|
// Tempo
|
||||||
setupSkipSilenceControl(rootView);
|
tempoSlider = Objects.requireNonNull(rootView.findViewById(R.id.tempoSeekbar));
|
||||||
setupAdjustBySemitonesControl(rootView);
|
tempoCurrentText = Objects.requireNonNull(rootView.findViewById(R.id.tempoCurrentText));
|
||||||
|
tempoStepUpText = Objects.requireNonNull(rootView.findViewById(R.id.tempoStepUp));
|
||||||
|
tempoStepDownText = Objects.requireNonNull(rootView.findViewById(R.id.tempoStepDown));
|
||||||
|
|
||||||
setupTempoControl(rootView);
|
setText(rootView, R.id.tempoMinimumText, PlayerHelper::formatSpeed, MINIMUM_PLAYBACK_VALUE);
|
||||||
setupPitchControl(rootView);
|
setText(rootView, R.id.tempoMaximumText, PlayerHelper::formatSpeed, MAXIMUM_PLAYBACK_VALUE);
|
||||||
setupSemitoneControl(rootView);
|
|
||||||
|
|
||||||
togglePitchSliderType(rootView);
|
// Pitch
|
||||||
|
pitchSlider = Objects.requireNonNull(rootView.findViewById(R.id.pitchSeekbar));
|
||||||
|
pitchCurrentText = Objects.requireNonNull(rootView.findViewById(R.id.pitchCurrentText));
|
||||||
|
pitchStepUpText = Objects.requireNonNull(rootView.findViewById(R.id.pitchStepUp));
|
||||||
|
pitchStepDownText = Objects.requireNonNull(rootView.findViewById(R.id.pitchStepDown));
|
||||||
|
|
||||||
setupStepSizeSelector(rootView);
|
setText(rootView, R.id.pitchMinimumText, PlayerHelper::formatPitch, MINIMUM_PLAYBACK_VALUE);
|
||||||
|
setText(rootView, R.id.pitchMaximumText, PlayerHelper::formatPitch, MAXIMUM_PLAYBACK_VALUE);
|
||||||
|
|
||||||
|
// Steps
|
||||||
|
setupStepTextView(rootView, R.id.stepSizeOnePercent, STEP_1_PERCENT_VALUE);
|
||||||
|
setupStepTextView(rootView, R.id.stepSizeFivePercent, STEP_5_PERCENT_VALUE);
|
||||||
|
setupStepTextView(rootView, R.id.stepSizeTenPercent, STEP_10_PERCENT_VALUE);
|
||||||
|
setupStepTextView(rootView, R.id.stepSizeTwentyFivePercent, STEP_25_PERCENT_VALUE);
|
||||||
|
setupStepTextView(rootView, R.id.stepSizeOneHundredPercent, STEP_100_PERCENT_VALUE);
|
||||||
|
|
||||||
|
// Bottom controls
|
||||||
|
unhookingCheckbox =
|
||||||
|
Objects.requireNonNull(rootView.findViewById(R.id.unhookCheckbox));
|
||||||
|
skipSilenceCheckbox =
|
||||||
|
Objects.requireNonNull(rootView.findViewById(R.id.skipSilenceCheckbox));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void togglePitchSliderType(@NonNull final View rootView) {
|
private TextView setText(
|
||||||
final RelativeLayout pitchControl = rootView.findViewById(R.id.pitchControl);
|
final TextView textView,
|
||||||
final RelativeLayout semitoneControl = rootView.findViewById(R.id.semitoneControl);
|
final DoubleFunction<String> formatter,
|
||||||
|
final double value
|
||||||
final View separatorStepSizeSelector =
|
) {
|
||||||
rootView.findViewById(R.id.separatorStepSizeSelector);
|
Objects.requireNonNull(textView).setText(formatter.apply(value));
|
||||||
final RelativeLayout.LayoutParams params =
|
return textView;
|
||||||
(RelativeLayout.LayoutParams) separatorStepSizeSelector.getLayoutParams();
|
|
||||||
if (pitchControl != null && semitoneControl != null && unhookingCheckbox != null) {
|
|
||||||
if (getCurrentAdjustBySemitones()) {
|
|
||||||
// replaces pitchControl slider with semitoneControl slider
|
|
||||||
pitchControl.setVisibility(View.GONE);
|
|
||||||
semitoneControl.setVisibility(View.VISIBLE);
|
|
||||||
params.addRule(RelativeLayout.BELOW, R.id.semitoneControl);
|
|
||||||
|
|
||||||
// forces unhook for semitones
|
|
||||||
unhookingCheckbox.setChecked(true);
|
|
||||||
unhookingCheckbox.setEnabled(false);
|
|
||||||
|
|
||||||
setupTempoStepSizeSelector(rootView);
|
|
||||||
} else {
|
|
||||||
semitoneControl.setVisibility(View.GONE);
|
|
||||||
pitchControl.setVisibility(View.VISIBLE);
|
|
||||||
params.addRule(RelativeLayout.BELOW, R.id.pitchControl);
|
|
||||||
|
|
||||||
// (re)enables hooking selection
|
|
||||||
unhookingCheckbox.setEnabled(true);
|
|
||||||
setupCombinedStepSizeSelector(rootView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupTempoControl(@NonNull final View rootView) {
|
private TextView setText(
|
||||||
tempoSlider = rootView.findViewById(R.id.tempoSeekbar);
|
final View rootView,
|
||||||
final TextView tempoMinimumText = rootView.findViewById(R.id.tempoMinimumText);
|
@IdRes final int idRes,
|
||||||
final TextView tempoMaximumText = rootView.findViewById(R.id.tempoMaximumText);
|
final DoubleFunction<String> formatter,
|
||||||
tempoCurrentText = rootView.findViewById(R.id.tempoCurrentText);
|
final double value
|
||||||
tempoStepUpText = rootView.findViewById(R.id.tempoStepUp);
|
) {
|
||||||
tempoStepDownText = rootView.findViewById(R.id.tempoStepDown);
|
final TextView textView = rootView.findViewById(idRes);
|
||||||
|
setText(textView, formatter, value);
|
||||||
if (tempoCurrentText != null) {
|
return textView;
|
||||||
tempoCurrentText.setText(PlayerHelper.formatSpeed(tempo));
|
|
||||||
}
|
|
||||||
if (tempoMaximumText != null) {
|
|
||||||
tempoMaximumText.setText(PlayerHelper.formatSpeed(MAXIMUM_PLAYBACK_VALUE));
|
|
||||||
}
|
|
||||||
if (tempoMinimumText != null) {
|
|
||||||
tempoMinimumText.setText(PlayerHelper.formatSpeed(MINIMUM_PLAYBACK_VALUE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tempoSlider != null) {
|
private void setupStepTextView(
|
||||||
tempoSlider.setMax(strategy.progressOf(MAXIMUM_PLAYBACK_VALUE));
|
final View rootView,
|
||||||
tempoSlider.setProgress(strategy.progressOf(tempo));
|
@IdRes final int idRes,
|
||||||
tempoSlider.setOnSeekBarChangeListener(getOnTempoChangedListener());
|
final double stepSizeValue
|
||||||
}
|
) {
|
||||||
|
setText(rootView, idRes, PlaybackParameterDialog::getPercentString, stepSizeValue)
|
||||||
|
.setOnClickListener(view -> setAndUpdateStepSize(stepSizeValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupPitchControl(@NonNull final View rootView) {
|
private void initUIData() {
|
||||||
pitchSlider = rootView.findViewById(R.id.pitchSeekbar);
|
// Tempo
|
||||||
final TextView pitchMinimumText = rootView.findViewById(R.id.pitchMinimumText);
|
tempoSlider.setMax(QUADRATIC_STRATEGY.progressOf(MAXIMUM_PLAYBACK_VALUE));
|
||||||
final TextView pitchMaximumText = rootView.findViewById(R.id.pitchMaximumText);
|
setAndUpdateTempo(tempo);
|
||||||
pitchCurrentText = rootView.findViewById(R.id.pitchCurrentText);
|
tempoSlider.setOnSeekBarChangeListener(
|
||||||
pitchStepDownText = rootView.findViewById(R.id.pitchStepDown);
|
getTempoOrPitchSeekbarChangeListener(this::onTempoSliderUpdated));
|
||||||
pitchStepUpText = rootView.findViewById(R.id.pitchStepUp);
|
|
||||||
|
|
||||||
if (pitchCurrentText != null) {
|
registerOnStepClickListener(
|
||||||
pitchCurrentText.setText(PlayerHelper.formatPitch(pitch));
|
tempoStepDownText, tempo, -1, this::onTempoSliderUpdated);
|
||||||
}
|
registerOnStepClickListener(
|
||||||
if (pitchMaximumText != null) {
|
tempoStepUpText, tempo, 1, this::onTempoSliderUpdated);
|
||||||
pitchMaximumText.setText(PlayerHelper.formatPitch(MAXIMUM_PLAYBACK_VALUE));
|
|
||||||
}
|
|
||||||
if (pitchMinimumText != null) {
|
|
||||||
pitchMinimumText.setText(PlayerHelper.formatPitch(MINIMUM_PLAYBACK_VALUE));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pitchSlider != null) {
|
// Pitch
|
||||||
pitchSlider.setMax(strategy.progressOf(MAXIMUM_PLAYBACK_VALUE));
|
pitchSlider.setMax(QUADRATIC_STRATEGY.progressOf(MAXIMUM_PLAYBACK_VALUE));
|
||||||
pitchSlider.setProgress(strategy.progressOf(pitch));
|
setAndUpdatePitch(pitch);
|
||||||
pitchSlider.setOnSeekBarChangeListener(getOnPitchChangedListener());
|
pitchSlider.setOnSeekBarChangeListener(
|
||||||
}
|
getTempoOrPitchSeekbarChangeListener(this::onPitchSliderUpdated));
|
||||||
}
|
|
||||||
|
|
||||||
private void setupSemitoneControl(@NonNull final View rootView) {
|
registerOnStepClickListener(
|
||||||
semitoneSlider = rootView.findViewById(R.id.semitoneSeekbar);
|
pitchStepDownText, pitch, -1, this::onPitchSliderUpdated);
|
||||||
semitoneCurrentText = rootView.findViewById(R.id.semitoneCurrentText);
|
registerOnStepClickListener(
|
||||||
semitoneStepDownText = rootView.findViewById(R.id.semitoneStepDown);
|
pitchStepUpText, pitch, 1, this::onPitchSliderUpdated);
|
||||||
semitoneStepUpText = rootView.findViewById(R.id.semitoneStepUp);
|
|
||||||
|
|
||||||
if (semitoneCurrentText != null) {
|
// Steps
|
||||||
semitoneCurrentText.setText(getSignedSemitonesString(semitones));
|
setAndUpdateStepSize(stepSize);
|
||||||
}
|
|
||||||
|
|
||||||
if (semitoneSlider != null) {
|
// Bottom controls
|
||||||
setSemitoneSlider(semitones);
|
// restore whether pitch and tempo are unhooked or not
|
||||||
semitoneSlider.setOnSeekBarChangeListener(getOnSemitoneChangedListener());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupHookingControl(@NonNull final View rootView) {
|
|
||||||
unhookingCheckbox = rootView.findViewById(R.id.unhookCheckbox);
|
|
||||||
if (unhookingCheckbox != null) {
|
|
||||||
// restores whether pitch and tempo are unhooked or not
|
|
||||||
unhookingCheckbox.setChecked(PreferenceManager
|
unhookingCheckbox.setChecked(PreferenceManager
|
||||||
.getDefaultSharedPreferences(requireContext())
|
.getDefaultSharedPreferences(requireContext())
|
||||||
.getBoolean(getString(R.string.playback_unhook_key), true));
|
.getBoolean(getString(R.string.playback_unhook_key), true));
|
||||||
|
|
||||||
unhookingCheckbox.setOnCheckedChangeListener((compoundButton, isChecked) -> {
|
unhookingCheckbox.setOnCheckedChangeListener((compoundButton, isChecked) -> {
|
||||||
// saves whether pitch and tempo are unhooked or not
|
// save whether pitch and tempo are unhooked or not
|
||||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
||||||
.edit()
|
.edit()
|
||||||
.putBoolean(getString(R.string.playback_unhook_key), isChecked)
|
.putBoolean(getString(R.string.playback_unhook_key), isChecked)
|
||||||
.apply();
|
.apply();
|
||||||
|
|
||||||
if (!isChecked) {
|
if (!isChecked) {
|
||||||
// when unchecked, slides back to the minimum of current tempo or pitch
|
// when unchecked, slide back to the minimum of current tempo or pitch
|
||||||
final double minimum = Math.min(getCurrentPitch(), getCurrentTempo());
|
setSliders(Math.min(pitch, tempo));
|
||||||
setSliders(minimum);
|
|
||||||
setCurrentPlaybackParameters();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
setAndUpdateSkipSilence(skipSilence);
|
||||||
|
skipSilenceCheckbox.setOnCheckedChangeListener((compoundButton, isChecked) -> {
|
||||||
|
skipSilence = isChecked;
|
||||||
|
updateCallback();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupSkipSilenceControl(@NonNull final View rootView) {
|
private void registerOnStepClickListener(
|
||||||
skipSilenceCheckbox = rootView.findViewById(R.id.skipSilenceCheckbox);
|
final TextView stepTextView,
|
||||||
if (skipSilenceCheckbox != null) {
|
final double currentValue,
|
||||||
skipSilenceCheckbox.setChecked(initialSkipSilence);
|
final double direction, // -1 for step down, +1 for step up
|
||||||
skipSilenceCheckbox.setOnCheckedChangeListener((compoundButton, isChecked) ->
|
final DoubleConsumer newValueConsumer
|
||||||
setCurrentPlaybackParameters());
|
) {
|
||||||
}
|
stepTextView.setOnClickListener(view ->
|
||||||
}
|
newValueConsumer.accept(currentValue * direction)
|
||||||
|
|
||||||
private void setupAdjustBySemitonesControl(@NonNull final View rootView) {
|
|
||||||
adjustBySemitonesCheckbox = rootView.findViewById(R.id.adjustBySemitonesCheckbox);
|
|
||||||
if (adjustBySemitonesCheckbox != null) {
|
|
||||||
// restores whether semitone adjustment is used or not
|
|
||||||
adjustBySemitonesCheckbox.setChecked(PreferenceManager
|
|
||||||
.getDefaultSharedPreferences(requireContext())
|
|
||||||
.getBoolean(getString(R.string.playback_adjust_by_semitones_key), true));
|
|
||||||
|
|
||||||
// stores whether semitone adjustment is used or not
|
|
||||||
adjustBySemitonesCheckbox.setOnCheckedChangeListener((compoundButton, isChecked) -> {
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
|
||||||
.edit()
|
|
||||||
.putBoolean(getString(R.string.playback_adjust_by_semitones_key), isChecked)
|
|
||||||
.apply();
|
|
||||||
togglePitchSliderType(rootView);
|
|
||||||
if (isChecked) {
|
|
||||||
setPlaybackParameters(
|
|
||||||
getCurrentTempo(),
|
|
||||||
getCurrentPitch(),
|
|
||||||
Integer.min(12,
|
|
||||||
Integer.max(-12, percentToSemitones(getCurrentPitch())
|
|
||||||
)),
|
|
||||||
getCurrentSkipSilence()
|
|
||||||
);
|
);
|
||||||
setSemitoneSlider(Integer.min(12,
|
|
||||||
Integer.max(-12, percentToSemitones(getCurrentPitch()))
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
setPlaybackParameters(
|
|
||||||
getCurrentTempo(),
|
|
||||||
semitonesToPercent(getCurrentSemitones()),
|
|
||||||
getCurrentSemitones(),
|
|
||||||
getCurrentSkipSilence()
|
|
||||||
);
|
|
||||||
setPitchSlider(semitonesToPercent(getCurrentSemitones()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupStepSizeSelector(@NonNull final View rootView) {
|
private void setAndUpdateStepSize(final double newStepSize) {
|
||||||
setStepSize(PreferenceManager
|
this.stepSize = newStepSize;
|
||||||
.getDefaultSharedPreferences(requireContext())
|
|
||||||
.getFloat(getString(R.string.adjustment_step_key), (float) DEFAULT_STEP));
|
|
||||||
|
|
||||||
final TextView stepSizeOnePercentText = rootView.findViewById(R.id.stepSizeOnePercent);
|
tempoStepUpText.setText(getStepUpPercentString(newStepSize));
|
||||||
final TextView stepSizeFivePercentText = rootView.findViewById(R.id.stepSizeFivePercent);
|
tempoStepDownText.setText(getStepDownPercentString(newStepSize));
|
||||||
final TextView stepSizeTenPercentText = rootView.findViewById(R.id.stepSizeTenPercent);
|
|
||||||
final TextView stepSizeTwentyFivePercentText = rootView
|
|
||||||
.findViewById(R.id.stepSizeTwentyFivePercent);
|
|
||||||
final TextView stepSizeOneHundredPercentText = rootView
|
|
||||||
.findViewById(R.id.stepSizeOneHundredPercent);
|
|
||||||
|
|
||||||
if (stepSizeOnePercentText != null) {
|
pitchStepUpText.setText(getStepUpPercentString(newStepSize));
|
||||||
stepSizeOnePercentText.setText(getPercentString(STEP_ONE_PERCENT_VALUE));
|
pitchStepDownText.setText(getStepDownPercentString(newStepSize));
|
||||||
stepSizeOnePercentText
|
|
||||||
.setOnClickListener(view -> setStepSize(STEP_ONE_PERCENT_VALUE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stepSizeFivePercentText != null) {
|
private void setAndUpdateSkipSilence(final boolean newSkipSilence) {
|
||||||
stepSizeFivePercentText.setText(getPercentString(STEP_FIVE_PERCENT_VALUE));
|
this.skipSilence = newSkipSilence;
|
||||||
stepSizeFivePercentText
|
skipSilenceCheckbox.setChecked(newSkipSilence);
|
||||||
.setOnClickListener(view -> setStepSize(STEP_FIVE_PERCENT_VALUE));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stepSizeTenPercentText != null) {
|
|
||||||
stepSizeTenPercentText.setText(getPercentString(STEP_TEN_PERCENT_VALUE));
|
|
||||||
stepSizeTenPercentText
|
|
||||||
.setOnClickListener(view -> setStepSize(STEP_TEN_PERCENT_VALUE));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stepSizeTwentyFivePercentText != null) {
|
|
||||||
stepSizeTwentyFivePercentText
|
|
||||||
.setText(getPercentString(STEP_TWENTY_FIVE_PERCENT_VALUE));
|
|
||||||
stepSizeTwentyFivePercentText
|
|
||||||
.setOnClickListener(view -> setStepSize(STEP_TWENTY_FIVE_PERCENT_VALUE));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stepSizeOneHundredPercentText != null) {
|
|
||||||
stepSizeOneHundredPercentText
|
|
||||||
.setText(getPercentString(STEP_ONE_HUNDRED_PERCENT_VALUE));
|
|
||||||
stepSizeOneHundredPercentText
|
|
||||||
.setOnClickListener(view -> setStepSize(STEP_ONE_HUNDRED_PERCENT_VALUE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupTempoStepSizeSelector(@NonNull final View rootView) {
|
|
||||||
final TextView playbackStepTypeText = rootView.findViewById(R.id.playback_step_type);
|
|
||||||
if (playbackStepTypeText != null) {
|
|
||||||
playbackStepTypeText.setText(R.string.playback_tempo_step);
|
|
||||||
}
|
|
||||||
setupStepSizeSelector(rootView);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupCombinedStepSizeSelector(@NonNull final View rootView) {
|
|
||||||
final TextView playbackStepTypeText = rootView.findViewById(R.id.playback_step_type);
|
|
||||||
if (playbackStepTypeText != null) {
|
|
||||||
playbackStepTypeText.setText(R.string.playback_step);
|
|
||||||
}
|
|
||||||
setupStepSizeSelector(rootView);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setStepSize(final double stepSize) {
|
|
||||||
PreferenceManager.getDefaultSharedPreferences(requireContext())
|
|
||||||
.edit()
|
|
||||||
.putFloat(getString(R.string.adjustment_step_key), (float) stepSize)
|
|
||||||
.apply();
|
|
||||||
|
|
||||||
if (tempoStepUpText != null) {
|
|
||||||
tempoStepUpText.setText(getStepUpPercentString(stepSize));
|
|
||||||
tempoStepUpText.setOnClickListener(view -> {
|
|
||||||
onTempoSliderUpdated(getCurrentTempo() + stepSize);
|
|
||||||
setCurrentPlaybackParameters();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tempoStepDownText != null) {
|
|
||||||
tempoStepDownText.setText(getStepDownPercentString(stepSize));
|
|
||||||
tempoStepDownText.setOnClickListener(view -> {
|
|
||||||
onTempoSliderUpdated(getCurrentTempo() - stepSize);
|
|
||||||
setCurrentPlaybackParameters();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pitchStepUpText != null) {
|
|
||||||
pitchStepUpText.setText(getStepUpPercentString(stepSize));
|
|
||||||
pitchStepUpText.setOnClickListener(view -> {
|
|
||||||
onPitchSliderUpdated(getCurrentPitch() + stepSize);
|
|
||||||
setCurrentPlaybackParameters();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pitchStepDownText != null) {
|
|
||||||
pitchStepDownText.setText(getStepDownPercentString(stepSize));
|
|
||||||
pitchStepDownText.setOnClickListener(view -> {
|
|
||||||
onPitchSliderUpdated(getCurrentPitch() - stepSize);
|
|
||||||
setCurrentPlaybackParameters();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semitoneStepDownText != null) {
|
|
||||||
semitoneStepDownText.setOnClickListener(view -> {
|
|
||||||
onSemitoneSliderUpdated(getCurrentSemitones() - 1);
|
|
||||||
setCurrentPlaybackParameters();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semitoneStepUpText != null) {
|
|
||||||
semitoneStepUpText.setOnClickListener(view -> {
|
|
||||||
onSemitoneSliderUpdated(getCurrentSemitones() + 1);
|
|
||||||
setCurrentPlaybackParameters();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Sliders
|
// Sliders
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
private SimpleOnSeekBarChangeListener getOnTempoChangedListener() {
|
private SeekBar.OnSeekBarChangeListener getTempoOrPitchSeekbarChangeListener(
|
||||||
return new SimpleOnSeekBarChangeListener() {
|
final DoubleConsumer newValueConsumer
|
||||||
|
) {
|
||||||
|
return new SeekBar.OnSeekBarChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(@NonNull final SeekBar seekBar, final int progress,
|
public void onProgressChanged(final SeekBar seekBar, final int progress,
|
||||||
final boolean fromUser) {
|
final boolean fromUser) {
|
||||||
final double currentTempo = strategy.valueOf(progress);
|
if (fromUser) { // this change is first in chain
|
||||||
if (fromUser) {
|
newValueConsumer.accept(QUADRATIC_STRATEGY.valueOf(progress));
|
||||||
onTempoSliderUpdated(currentTempo);
|
updateCallback();
|
||||||
setCurrentPlaybackParameters();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private SimpleOnSeekBarChangeListener getOnPitchChangedListener() {
|
|
||||||
return new SimpleOnSeekBarChangeListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(@NonNull final SeekBar seekBar, final int progress,
|
public void onStartTrackingTouch(final SeekBar seekBar) {
|
||||||
final boolean fromUser) {
|
// Do nothing
|
||||||
final double currentPitch = strategy.valueOf(progress);
|
|
||||||
if (fromUser) { // this change is first in chain
|
|
||||||
onPitchSliderUpdated(currentPitch);
|
|
||||||
setCurrentPlaybackParameters();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimpleOnSeekBarChangeListener getOnSemitoneChangedListener() {
|
|
||||||
return new SimpleOnSeekBarChangeListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(@NonNull final SeekBar seekBar, final int progress,
|
public void onStopTrackingTouch(final SeekBar seekBar) {
|
||||||
final boolean fromUser) {
|
// Do nothing
|
||||||
// semitone slider supplies values 0 to 24, subtraction by 12 is required
|
|
||||||
final int currentSemitones = progress - 12;
|
|
||||||
if (fromUser) { // this change is first in chain
|
|
||||||
onSemitoneSliderUpdated(currentSemitones);
|
|
||||||
// line below also saves semitones as pitch percentages
|
|
||||||
onPitchSliderUpdated(semitonesToPercent(currentSemitones));
|
|
||||||
setCurrentPlaybackParameters();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -545,7 +336,7 @@ public class PlaybackParameterDialog extends DialogFragment {
|
|||||||
if (!unhookingCheckbox.isChecked()) {
|
if (!unhookingCheckbox.isChecked()) {
|
||||||
setSliders(newTempo);
|
setSliders(newTempo);
|
||||||
} else {
|
} else {
|
||||||
setTempoSlider(newTempo);
|
setAndUpdateTempo(newTempo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,109 +344,53 @@ public class PlaybackParameterDialog extends DialogFragment {
|
|||||||
if (!unhookingCheckbox.isChecked()) {
|
if (!unhookingCheckbox.isChecked()) {
|
||||||
setSliders(newPitch);
|
setSliders(newPitch);
|
||||||
} else {
|
} else {
|
||||||
setPitchSlider(newPitch);
|
setAndUpdatePitch(newPitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onSemitoneSliderUpdated(final int newSemitone) {
|
|
||||||
setSemitoneSlider(newSemitone);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSliders(final double newValue) {
|
private void setSliders(final double newValue) {
|
||||||
setTempoSlider(newValue);
|
setAndUpdateTempo(newValue);
|
||||||
setPitchSlider(newValue);
|
setAndUpdatePitch(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTempoSlider(final double newTempo) {
|
private void setAndUpdateTempo(final double newTempo) {
|
||||||
if (tempoSlider == null) {
|
this.tempo = newTempo;
|
||||||
return;
|
tempoSlider.setProgress(QUADRATIC_STRATEGY.progressOf(tempo));
|
||||||
}
|
setText(tempoCurrentText, PlayerHelper::formatSpeed, tempo);
|
||||||
tempoSlider.setProgress(strategy.progressOf(newTempo));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setPitchSlider(final double newPitch) {
|
private void setAndUpdatePitch(final double newPitch) {
|
||||||
if (pitchSlider == null) {
|
this.pitch = newPitch;
|
||||||
return;
|
pitchSlider.setProgress(QUADRATIC_STRATEGY.progressOf(pitch));
|
||||||
}
|
setText(pitchCurrentText, PlayerHelper::formatPitch, pitch);
|
||||||
pitchSlider.setProgress(strategy.progressOf(newPitch));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSemitoneSlider(final int newSemitone) {
|
|
||||||
if (semitoneSlider == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
semitoneSlider.setProgress(newSemitone + 12);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Helper
|
// Helper
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
private void setCurrentPlaybackParameters() {
|
private void updateCallback() {
|
||||||
if (getCurrentAdjustBySemitones()) {
|
if (callback == null) {
|
||||||
setPlaybackParameters(
|
return;
|
||||||
getCurrentTempo(),
|
|
||||||
semitonesToPercent(getCurrentSemitones()),
|
|
||||||
getCurrentSemitones(),
|
|
||||||
getCurrentSkipSilence()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
setPlaybackParameters(
|
|
||||||
getCurrentTempo(),
|
|
||||||
getCurrentPitch(),
|
|
||||||
percentToSemitones(getCurrentPitch()),
|
|
||||||
getCurrentSkipSilence()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void setPlaybackParameters(final double newTempo, final double newPitch,
|
|
||||||
final int newSemitones, final boolean skipSilence) {
|
|
||||||
if (callback != null && tempoCurrentText != null
|
|
||||||
&& pitchCurrentText != null && semitoneCurrentText != null) {
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "Setting playback parameters to "
|
Log.d(TAG, "Updating callback: "
|
||||||
+ "tempo=[" + newTempo + "], "
|
+ "tempo = [" + tempo + "], "
|
||||||
+ "pitch=[" + newPitch + "], "
|
+ "pitch = [" + pitch + "], "
|
||||||
+ "semitones=[" + newSemitones + "]");
|
+ "skipSilence = [" + skipSilence + "]"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
callback.onPlaybackParameterChanged((float) tempo, (float) pitch, skipSilence);
|
||||||
tempoCurrentText.setText(PlayerHelper.formatSpeed(newTempo));
|
|
||||||
pitchCurrentText.setText(PlayerHelper.formatPitch(newPitch));
|
|
||||||
semitoneCurrentText.setText(getSignedSemitonesString(newSemitones));
|
|
||||||
callback.onPlaybackParameterChanged((float) newTempo, (float) newPitch, skipSilence);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private double getCurrentTempo() {
|
|
||||||
return tempoSlider == null ? tempo : strategy.valueOf(tempoSlider.getProgress());
|
|
||||||
}
|
|
||||||
|
|
||||||
private double getCurrentPitch() {
|
|
||||||
return pitchSlider == null ? pitch : strategy.valueOf(pitchSlider.getProgress());
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getCurrentSemitones() {
|
|
||||||
// semitoneSlider is absolute, that's why - 12
|
|
||||||
return semitoneSlider == null ? semitones : semitoneSlider.getProgress() - 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean getCurrentSkipSilence() {
|
|
||||||
return skipSilenceCheckbox != null && skipSilenceCheckbox.isChecked();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean getCurrentAdjustBySemitones() {
|
|
||||||
return adjustBySemitonesCheckbox != null && adjustBySemitonesCheckbox.isChecked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static String getStepUpPercentString(final double percent) {
|
private static String getStepUpPercentString(final double percent) {
|
||||||
return STEP_UP_SIGN + getPercentString(percent);
|
return '+' + getPercentString(percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private static String getStepDownPercentString(final double percent) {
|
private static String getStepDownPercentString(final double percent) {
|
||||||
return STEP_DOWN_SIGN + getPercentString(percent);
|
return '-' + getPercentString(percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -663,21 +398,8 @@ public class PlaybackParameterDialog extends DialogFragment {
|
|||||||
return PlayerHelper.formatPitch(percent);
|
return PlayerHelper.formatPitch(percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private static String getSignedSemitonesString(final int semitones) {
|
|
||||||
return semitones > 0 ? "+" + semitones : "" + semitones;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Callback {
|
public interface Callback {
|
||||||
void onPlaybackParameterChanged(float playbackTempo, float playbackPitch,
|
void onPlaybackParameterChanged(float playbackTempo, float playbackPitch,
|
||||||
boolean playbackSkipSilence);
|
boolean playbackSkipSilence);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double semitonesToPercent(final int inSemitones) {
|
|
||||||
return Math.pow(2, inSemitones / 12.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int percentToSemitones(final double inPercent) {
|
|
||||||
return (int) Math.round(12 * Math.log(inPercent) / Math.log(2));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user