add preserve pitch option (#972)

This commit is contained in:
Lyall 2025-06-28 21:18:08 +01:00 committed by GitHub
parent c382e01f64
commit 81ca6937bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 36 additions and 9 deletions

View file

@ -705,6 +705,8 @@
"volumeWidth_description": "the width of the volume slider",
"webAudio": "use web audio",
"webAudio_description": "use web audio. this enables advanced features like replaygain. disable if you experience otherwise",
"preservePitch": "preserve pitch",
"preservePitch_description": "preserves pitch when modifying playback speed",
"windowBarStyle": "window bar style",
"windowBarStyle_description": "select the style of the window bar",
"zoom": "zoom percentage",

View file

@ -120,6 +120,7 @@ export const AudioPlayer = forwardRef<AudioPlayerRef, AudioPlayerProps>((props,
const audioDeviceId = useSettingsStore((state) => state.playback.audioDeviceId);
const playback = useSettingsStore((state) => state.playback.mpvProperties);
const shouldUseWebAudio = useSettingsStore((state) => state.playback.webAudio);
const preservesPitch = useSettingsStore((state) => state.playback.preservePitch);
const { resetSampleRate } = useSettingsStoreActions();
const playbackSpeed = useSpeed();
const { transcode } = usePlaybackSettings();
@ -230,21 +231,23 @@ export const AudioPlayer = forwardRef<AudioPlayerRef, AudioPlayerProps>((props,
// calling play() is not necessarily a safe option (https://developer.chrome.com/blog/play-request-was-interrupted)
// In practice, this failure is only likely to happen when using the 0-second wav:
// play() + play() in rapid succession will cause problems as the frist one ends the track.
player1Ref.current
?.getInternalPlayer()
?.play()
.catch(() => {});
const internalPlayer = player1Ref.current?.getInternalPlayer();
if (internalPlayer) {
internalPlayer.preservesPitch = preservesPitch;
internalPlayer.play().catch(() => {});
}
} else {
player2Ref.current
?.getInternalPlayer()
?.play()
.catch(() => {});
const internalPlayer = player2Ref.current?.getInternalPlayer();
if (internalPlayer) {
internalPlayer.preservesPitch = preservesPitch;
internalPlayer.play().catch(() => {});
}
}
} else {
player1Ref.current?.getInternalPlayer()?.pause();
player2Ref.current?.getInternalPlayer()?.pause();
}
}, [currentPlayer, status]);
}, [currentPlayer, status, preservesPitch]);
const handleCrossfade1 = useCallback(
(e: AudioPlayerProgress) => {

View file

@ -155,6 +155,26 @@ export const AudioSettings = ({ hasFancyAudio }: { hasFancyAudio: boolean }) =>
postProcess: 'sentenceCase',
}),
},
{
control: (
<Switch
defaultChecked={settings.preservePitch}
onChange={(e) => {
setSettings({
playback: { ...settings, preservePitch: e.currentTarget.checked },
});
}}
/>
),
description: t('setting.preservePitch', {
context: 'description',
postProcess: 'sentenceCase',
}),
isHidden: settings.type !== PlaybackType.WEB,
title: t('setting.preservePitch', {
postProcess: 'sentenceCase',
}),
},
{
control: (
<Slider

View file

@ -281,6 +281,7 @@ export interface SettingsState {
mpvExtraParameters: string[];
mpvProperties: MpvSettings;
muted: boolean;
preservePitch: boolean;
scrobble: {
enabled: boolean;
scrobbleAtDuration: number;
@ -473,6 +474,7 @@ const initialState: SettingsState = {
replayGainPreampDB: 0,
},
muted: false,
preservePitch: true,
scrobble: {
enabled: true,
scrobbleAtDuration: 240,