mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
refactor(player): E.37 — extract updateReplayGainForCurrentTrack (#601)
Move the ~50-LOC `updateReplayGainForCurrentTrack` action body into `runUpdateReplayGainForCurrentTrack(set, get)` in a dedicated module, following the helper-with-thin-wrapper pattern from `applyQueueHistorySnapshot` (E.30) rather than a single-action factory. The action recomputes the normalization snapshot + pushes fresh ReplayGain/loudness state to the engine when mode toggles change or the loudness cache fills mid-playback. Pure code-move. playerStore.ts: 991 → 938 LOC (−53).
This commit is contained in:
committed by
GitHub
parent
55b2b12fa5
commit
14346d1482
@@ -11,8 +11,6 @@ import { useHotCacheStore } from './hotCacheStore';
|
||||
import { orbitBulkGuard } from '../utils/orbitBulkGuard';
|
||||
import { useOrbitStore } from './orbitStore';
|
||||
import { estimateLivePosition } from '../api/orbit';
|
||||
import { loudnessGainPlaceholderUntilCacheDb } from '../utils/loudnessPlaceholder';
|
||||
import { effectiveLoudnessPreAnalysisAttenuationDb } from '../utils/loudnessPreAnalysisSlider';
|
||||
import { resolveReplayGainDb } from '../utils/resolveReplayGainDb';
|
||||
import { shuffleArray } from '../utils/shuffleArray';
|
||||
import { songToTrack } from '../utils/songToTrack';
|
||||
@@ -37,16 +35,12 @@ import {
|
||||
import { deriveNormalizationSnapshot } from './normalizationSnapshot';
|
||||
import { isInOrbitSession } from './orbitSession';
|
||||
import {
|
||||
getCachedLoudnessGain,
|
||||
hasStableLoudness,
|
||||
isReplayGainActive,
|
||||
loudnessCacheStateKeysForTrackId,
|
||||
loudnessGainDbForEngineBind,
|
||||
} from './loudnessGainCache';
|
||||
import {
|
||||
clearAllPlaybackScheduleTimers,
|
||||
} from './scheduleTimers';
|
||||
import { invokeAudioUpdateReplayGainDeduped } from './normalizationIpcDedupe';
|
||||
import { touchHotCacheOnPlayback } from './hotCacheTouch';
|
||||
import { applySkipStarOnManualNext } from './skipStarRating';
|
||||
import { resetLoudnessBackfillStateForTrackId } from './loudnessBackfillState';
|
||||
@@ -149,6 +143,7 @@ import type { PlayerState, Track } from './playerStoreTypes';
|
||||
export type { PlayerState, Track };
|
||||
import { createLastfmActions } from './lastfmActions';
|
||||
import { createMiscActions } from './miscActions';
|
||||
import { runUpdateReplayGainForCurrentTrack } from './updateReplayGainAction';
|
||||
import { createQueueMutationActions } from './queueMutationActions';
|
||||
import { createScheduleActions } from './scheduleActions';
|
||||
import { createTransportLightActions } from './transportLightActions';
|
||||
@@ -902,55 +897,7 @@ export const usePlayerStore = create<PlayerState>()(
|
||||
});
|
||||
},
|
||||
|
||||
updateReplayGainForCurrentTrack: () => {
|
||||
const { currentTrack, queue, queueIndex, volume } = get();
|
||||
if (!currentTrack || !currentTrack.id) return;
|
||||
const authState = useAuthStore.getState();
|
||||
const prev = queueIndex > 0 ? queue[queueIndex - 1] : null;
|
||||
const next = queueIndex + 1 < queue.length ? queue[queueIndex + 1] : null;
|
||||
const replayGainDb = resolveReplayGainDb(
|
||||
currentTrack, prev, next,
|
||||
isReplayGainActive(), authState.replayGainMode,
|
||||
);
|
||||
const replayGainPeak = isReplayGainActive()
|
||||
? (currentTrack.replayGainPeak ?? null)
|
||||
: null;
|
||||
|
||||
const normalization = deriveNormalizationSnapshot(currentTrack, queue, queueIndex);
|
||||
const cachedLoud = getCachedLoudnessGain(currentTrack.id);
|
||||
const cachedLoudDb = Number.isFinite(cachedLoud) ? cachedLoud! : null;
|
||||
const haveStableLoud = hasStableLoudness(currentTrack.id);
|
||||
const preEffForNorm = effectiveLoudnessPreAnalysisAttenuationDb(
|
||||
authState.loudnessPreAnalysisAttenuationDb,
|
||||
authState.loudnessTargetLufs,
|
||||
);
|
||||
const preAnalysisPlaceholderDb =
|
||||
normalization.normalizationEngineLive === 'loudness'
|
||||
&& cachedLoudDb == null
|
||||
&& !haveStableLoud
|
||||
&& Number.isFinite(preEffForNorm)
|
||||
? loudnessGainPlaceholderUntilCacheDb(
|
||||
authState.loudnessTargetLufs,
|
||||
preEffForNorm,
|
||||
)
|
||||
: null;
|
||||
set(prevState => ({
|
||||
normalizationNowDb:
|
||||
normalization.normalizationEngineLive === 'loudness'
|
||||
? (cachedLoudDb ?? preAnalysisPlaceholderDb ?? prevState.normalizationNowDb)
|
||||
: normalization.normalizationNowDb,
|
||||
normalizationTargetLufs: normalization.normalizationTargetLufs,
|
||||
normalizationEngineLive: normalization.normalizationEngineLive,
|
||||
}));
|
||||
invokeAudioUpdateReplayGainDeduped({
|
||||
volume,
|
||||
replayGainDb,
|
||||
replayGainPeak,
|
||||
loudnessGainDb: currentTrack ? (getCachedLoudnessGain(currentTrack.id) ?? null) : null,
|
||||
preGainDb: authState.replayGainPreGainDb,
|
||||
fallbackDb: authState.replayGainFallbackDb,
|
||||
});
|
||||
},
|
||||
updateReplayGainForCurrentTrack: () => runUpdateReplayGainForCurrentTrack(set, get),
|
||||
};
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import { effectiveLoudnessPreAnalysisAttenuationDb } from '../utils/loudnessPreAnalysisSlider';
|
||||
import { loudnessGainPlaceholderUntilCacheDb } from '../utils/loudnessPlaceholder';
|
||||
import { resolveReplayGainDb } from '../utils/resolveReplayGainDb';
|
||||
import { useAuthStore } from './authStore';
|
||||
import {
|
||||
getCachedLoudnessGain,
|
||||
hasStableLoudness,
|
||||
isReplayGainActive,
|
||||
} from './loudnessGainCache';
|
||||
import { deriveNormalizationSnapshot } from './normalizationSnapshot';
|
||||
import { invokeAudioUpdateReplayGainDeduped } from './normalizationIpcDedupe';
|
||||
import type { PlayerState } from './playerStoreTypes';
|
||||
|
||||
type SetState = (
|
||||
partial: Partial<PlayerState> | ((state: PlayerState) => Partial<PlayerState>),
|
||||
) => void;
|
||||
type GetState = () => PlayerState;
|
||||
|
||||
/**
|
||||
* Recompute and push fresh ReplayGain + loudness state to the engine
|
||||
* for the currently-playing track. Called when ReplayGain mode /
|
||||
* pre-gain / fallback toggles change while a track is mid-playback,
|
||||
* or when the loudness cache for the current track resolves later
|
||||
* than the initial play.
|
||||
*
|
||||
* - Re-derives the normalization snapshot (target LUFS, engine-live
|
||||
* mode) from the current queue context.
|
||||
* - Picks a placeholder loudness gain when in loudness mode and the
|
||||
* real cached gain isn't ready yet, so the UI's "now playing -X dB"
|
||||
* readout doesn't drop to zero between the cache miss and the
|
||||
* eventual cache fill.
|
||||
* - Pushes the new audio parameters to the Rust engine via the
|
||||
* deduplicated IPC channel.
|
||||
*/
|
||||
export function runUpdateReplayGainForCurrentTrack(set: SetState, get: GetState): void {
|
||||
const { currentTrack, queue, queueIndex, volume } = get();
|
||||
if (!currentTrack || !currentTrack.id) return;
|
||||
const authState = useAuthStore.getState();
|
||||
const prev = queueIndex > 0 ? queue[queueIndex - 1] : null;
|
||||
const next = queueIndex + 1 < queue.length ? queue[queueIndex + 1] : null;
|
||||
const replayGainDb = resolveReplayGainDb(
|
||||
currentTrack, prev, next,
|
||||
isReplayGainActive(), authState.replayGainMode,
|
||||
);
|
||||
const replayGainPeak = isReplayGainActive()
|
||||
? (currentTrack.replayGainPeak ?? null)
|
||||
: null;
|
||||
|
||||
const normalization = deriveNormalizationSnapshot(currentTrack, queue, queueIndex);
|
||||
const cachedLoud = getCachedLoudnessGain(currentTrack.id);
|
||||
const cachedLoudDb = Number.isFinite(cachedLoud) ? cachedLoud! : null;
|
||||
const haveStableLoud = hasStableLoudness(currentTrack.id);
|
||||
const preEffForNorm = effectiveLoudnessPreAnalysisAttenuationDb(
|
||||
authState.loudnessPreAnalysisAttenuationDb,
|
||||
authState.loudnessTargetLufs,
|
||||
);
|
||||
const preAnalysisPlaceholderDb =
|
||||
normalization.normalizationEngineLive === 'loudness'
|
||||
&& cachedLoudDb == null
|
||||
&& !haveStableLoud
|
||||
&& Number.isFinite(preEffForNorm)
|
||||
? loudnessGainPlaceholderUntilCacheDb(
|
||||
authState.loudnessTargetLufs,
|
||||
preEffForNorm,
|
||||
)
|
||||
: null;
|
||||
set(prevState => ({
|
||||
normalizationNowDb:
|
||||
normalization.normalizationEngineLive === 'loudness'
|
||||
? (cachedLoudDb ?? preAnalysisPlaceholderDb ?? prevState.normalizationNowDb)
|
||||
: normalization.normalizationNowDb,
|
||||
normalizationTargetLufs: normalization.normalizationTargetLufs,
|
||||
normalizationEngineLive: normalization.normalizationEngineLive,
|
||||
}));
|
||||
invokeAudioUpdateReplayGainDeduped({
|
||||
volume,
|
||||
replayGainDb,
|
||||
replayGainPeak,
|
||||
loudnessGainDb: getCachedLoudnessGain(currentTrack.id) ?? null,
|
||||
preGainDb: authState.replayGainPreGainDb,
|
||||
fallbackDb: authState.replayGainFallbackDb,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user