2022-12-19 15:59:14 -08:00
|
|
|
import type { Dispatch } from 'react';
|
2025-05-18 14:03:18 -07:00
|
|
|
|
2022-12-19 15:59:14 -08:00
|
|
|
import { CrossfadeStyle } from '/@/renderer/types';
|
|
|
|
|
|
|
|
|
|
export const gaplessHandler = (args: {
|
2023-07-01 19:10:05 -07:00
|
|
|
currentTime: number;
|
|
|
|
|
duration: number;
|
|
|
|
|
isFlac: boolean;
|
|
|
|
|
isTransitioning: boolean;
|
|
|
|
|
nextPlayerRef: any;
|
|
|
|
|
setIsTransitioning: Dispatch<boolean>;
|
2022-12-19 15:59:14 -08:00
|
|
|
}) => {
|
2025-05-18 14:03:18 -07:00
|
|
|
const { currentTime, duration, isFlac, isTransitioning, nextPlayerRef, setIsTransitioning } =
|
2023-07-01 19:10:05 -07:00
|
|
|
args;
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
if (!isTransitioning) {
|
|
|
|
|
if (currentTime > duration - 2) {
|
|
|
|
|
return setIsTransitioning(true);
|
|
|
|
|
}
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
return null;
|
|
|
|
|
}
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
const durationPadding = isFlac ? 0.065 : 0.116;
|
|
|
|
|
if (currentTime + durationPadding >= duration) {
|
2024-01-28 01:50:51 -08:00
|
|
|
return nextPlayerRef.current
|
|
|
|
|
.getInternalPlayer()
|
|
|
|
|
?.play()
|
|
|
|
|
.catch(() => {});
|
2023-07-01 19:10:05 -07:00
|
|
|
}
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
return null;
|
2022-12-19 15:59:14 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export const crossfadeHandler = (args: {
|
2023-07-01 19:10:05 -07:00
|
|
|
currentPlayer: 1 | 2;
|
|
|
|
|
currentPlayerRef: any;
|
|
|
|
|
currentTime: number;
|
|
|
|
|
duration: number;
|
|
|
|
|
fadeDuration: number;
|
|
|
|
|
fadeType: CrossfadeStyle;
|
|
|
|
|
isTransitioning: boolean;
|
|
|
|
|
nextPlayerRef: any;
|
|
|
|
|
player: 1 | 2;
|
|
|
|
|
setIsTransitioning: Dispatch<boolean>;
|
|
|
|
|
volume: number;
|
2022-12-19 15:59:14 -08:00
|
|
|
}) => {
|
2023-07-01 19:10:05 -07:00
|
|
|
const {
|
|
|
|
|
currentPlayer,
|
|
|
|
|
currentPlayerRef,
|
2025-05-18 14:03:18 -07:00
|
|
|
currentTime,
|
|
|
|
|
duration,
|
2023-07-01 19:10:05 -07:00
|
|
|
fadeDuration,
|
|
|
|
|
fadeType,
|
|
|
|
|
isTransitioning,
|
2025-05-18 14:03:18 -07:00
|
|
|
nextPlayerRef,
|
|
|
|
|
player,
|
2023-07-01 19:10:05 -07:00
|
|
|
setIsTransitioning,
|
2025-05-18 14:03:18 -07:00
|
|
|
volume,
|
2023-07-01 19:10:05 -07:00
|
|
|
} = args;
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
if (!isTransitioning || currentPlayer !== player) {
|
2024-08-21 22:47:35 -07:00
|
|
|
// check for a large-enough duration, as the default audio element has some dummy audio
|
|
|
|
|
const shouldBeginTransition = duration > 0.5 && currentTime >= duration - fadeDuration;
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
if (shouldBeginTransition) {
|
|
|
|
|
setIsTransitioning(true);
|
2024-01-28 01:50:51 -08:00
|
|
|
return nextPlayerRef.current
|
|
|
|
|
.getInternalPlayer()
|
|
|
|
|
?.play()
|
|
|
|
|
.catch(() => {});
|
2023-07-01 19:10:05 -07:00
|
|
|
}
|
|
|
|
|
return null;
|
2022-12-19 15:59:14 -08:00
|
|
|
}
|
|
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
const timeLeft = duration - currentTime;
|
|
|
|
|
let currentPlayerVolumeCalculation;
|
|
|
|
|
let nextPlayerVolumeCalculation;
|
|
|
|
|
let percentageOfFadeLeft;
|
|
|
|
|
let n;
|
|
|
|
|
switch (fadeType) {
|
|
|
|
|
case 'dipped':
|
|
|
|
|
// https://math.stackexchange.com/a/4622
|
|
|
|
|
percentageOfFadeLeft = timeLeft / fadeDuration;
|
|
|
|
|
currentPlayerVolumeCalculation = percentageOfFadeLeft ** 2 * volume;
|
|
|
|
|
nextPlayerVolumeCalculation = (percentageOfFadeLeft - 1) ** 2 * volume;
|
|
|
|
|
break;
|
2025-05-18 14:03:18 -07:00
|
|
|
case 'equalPower':
|
|
|
|
|
// https://dsp.stackexchange.com/a/14755
|
|
|
|
|
percentageOfFadeLeft = (timeLeft / fadeDuration) * 2;
|
|
|
|
|
currentPlayerVolumeCalculation = Math.sqrt(0.5 * percentageOfFadeLeft) * volume;
|
|
|
|
|
nextPlayerVolumeCalculation = Math.sqrt(0.5 * (2 - percentageOfFadeLeft)) * volume;
|
|
|
|
|
break;
|
2023-07-01 19:10:05 -07:00
|
|
|
case fadeType.match(/constantPower.*/)?.input:
|
|
|
|
|
// https://math.stackexchange.com/a/26159
|
|
|
|
|
n =
|
|
|
|
|
fadeType === 'constantPower'
|
|
|
|
|
? 0
|
|
|
|
|
: fadeType === 'constantPowerSlowFade'
|
2024-08-23 08:19:27 -07:00
|
|
|
? 1
|
|
|
|
|
: fadeType === 'constantPowerSlowCut'
|
|
|
|
|
? 3
|
|
|
|
|
: 10;
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
percentageOfFadeLeft = timeLeft / fadeDuration;
|
|
|
|
|
currentPlayerVolumeCalculation =
|
|
|
|
|
Math.cos((Math.PI / 4) * ((2 * percentageOfFadeLeft - 1) ** (2 * n + 1) - 1)) *
|
|
|
|
|
volume;
|
|
|
|
|
nextPlayerVolumeCalculation =
|
|
|
|
|
Math.cos((Math.PI / 4) * ((2 * percentageOfFadeLeft - 1) ** (2 * n + 1) + 1)) *
|
|
|
|
|
volume;
|
|
|
|
|
break;
|
2025-05-18 14:03:18 -07:00
|
|
|
case 'linear':
|
|
|
|
|
currentPlayerVolumeCalculation = (timeLeft / fadeDuration) * volume;
|
|
|
|
|
nextPlayerVolumeCalculation = ((fadeDuration - timeLeft) / fadeDuration) * volume;
|
|
|
|
|
break;
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
default:
|
|
|
|
|
currentPlayerVolumeCalculation = (timeLeft / fadeDuration) * volume;
|
|
|
|
|
nextPlayerVolumeCalculation = ((fadeDuration - timeLeft) / fadeDuration) * volume;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
const currentPlayerVolume =
|
|
|
|
|
currentPlayerVolumeCalculation >= 0 ? currentPlayerVolumeCalculation : 0;
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
const nextPlayerVolume =
|
|
|
|
|
nextPlayerVolumeCalculation <= volume ? nextPlayerVolumeCalculation : volume;
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
if (currentPlayer === 1) {
|
|
|
|
|
currentPlayerRef.current.getInternalPlayer().volume = currentPlayerVolume;
|
|
|
|
|
nextPlayerRef.current.getInternalPlayer().volume = nextPlayerVolume;
|
|
|
|
|
} else {
|
|
|
|
|
currentPlayerRef.current.getInternalPlayer().volume = currentPlayerVolume;
|
|
|
|
|
nextPlayerRef.current.getInternalPlayer().volume = nextPlayerVolume;
|
|
|
|
|
}
|
|
|
|
|
// }
|
2022-12-19 15:59:14 -08:00
|
|
|
|
2023-07-01 19:10:05 -07:00
|
|
|
return null;
|
2022-12-19 15:59:14 -08:00
|
|
|
};
|