Add emit reverse option and retune echo/dice output
This commit is contained in:
@@ -71,14 +71,16 @@ export function connectEffectChain(
|
||||
}
|
||||
|
||||
if (effect === 'echo') {
|
||||
// Retune echo curve so 100 ~= previous 80, then increase decay (more fade) by reducing feedback.
|
||||
const tunedMix = effectMix * 0.8;
|
||||
const delay = audioCtx.createDelay(1);
|
||||
delay.delayTime.value = 0.04 + effectMix * 0.76;
|
||||
delay.delayTime.value = 0.04 + tunedMix * 0.76;
|
||||
const feedback = audioCtx.createGain();
|
||||
feedback.gain.value = 0.04 + effectMix * 0.88;
|
||||
feedback.gain.value = 0.02 + tunedMix * 0.44;
|
||||
const wetGain = audioCtx.createGain();
|
||||
wetGain.gain.value = 0.08 + effectMix * 0.92;
|
||||
wetGain.gain.value = 0.08 + tunedMix * 0.92;
|
||||
const dryGain = audioCtx.createGain();
|
||||
dryGain.gain.value = 1 - effectMix * 0.85;
|
||||
dryGain.gain.value = 1 - tunedMix * 0.85;
|
||||
|
||||
input.connect(dryGain);
|
||||
dryGain.connect(destination);
|
||||
|
||||
@@ -45,13 +45,23 @@ function setElementPreservesPitch(element: HTMLAudioElement, enabled: boolean):
|
||||
if ('webkitPreservesPitch' in target) target.webkitPreservesPitch = enabled;
|
||||
}
|
||||
|
||||
function resolveEmitRates(item: WorldItem): { playbackRate: number; preservePitch: boolean } {
|
||||
function setElementPlaybackRate(element: HTMLAudioElement, playbackRate: number, reverse: boolean): void {
|
||||
const targetRate = reverse ? -Math.abs(playbackRate) : Math.abs(playbackRate);
|
||||
element.playbackRate = targetRate;
|
||||
// Most browsers reject negative playbackRate for media elements; fall back gracefully.
|
||||
if (reverse && element.playbackRate >= 0) {
|
||||
element.playbackRate = Math.abs(playbackRate);
|
||||
}
|
||||
}
|
||||
|
||||
function resolveEmitRates(item: WorldItem): { playbackRate: number; preservePitch: boolean; reverse: boolean } {
|
||||
const globals = getItemTypeGlobalProperties(item.type);
|
||||
const speed = resolveEmitPlaybackRate(item.params.emitSoundSpeed ?? globals.emitSoundSpeed ?? 50);
|
||||
const tempo = resolveEmitPlaybackRate(item.params.emitSoundTempo ?? globals.emitSoundTempo ?? 50);
|
||||
const reverse = item.params.emitSoundReverse === true || (item.params.emitSoundReverse === undefined && globals.emitSoundReverse === true);
|
||||
const playbackRate = Math.max(0.25, Math.min(4, speed * tempo));
|
||||
const preservePitch = Math.abs(speed - 1) < 0.001;
|
||||
return { playbackRate, preservePitch };
|
||||
return { playbackRate, preservePitch, reverse };
|
||||
}
|
||||
|
||||
export class ItemEmitRuntime {
|
||||
@@ -133,7 +143,7 @@ export class ItemEmitRuntime {
|
||||
const effectRuntime = connectEffectChain(audioCtx, effectInput, gain, effect, effectValue);
|
||||
const initialRates = resolveEmitRates(item);
|
||||
setElementPreservesPitch(element, initialRates.preservePitch);
|
||||
element.playbackRate = initialRates.playbackRate;
|
||||
setElementPlaybackRate(element, initialRates.playbackRate, initialRates.reverse);
|
||||
if (this.audio.supportsStereoPanner()) {
|
||||
panner = audioCtx.createStereoPanner();
|
||||
gain.connect(panner).connect(audioCtx.destination);
|
||||
@@ -174,8 +184,11 @@ export class ItemEmitRuntime {
|
||||
const nextRates = resolveEmitRates(item);
|
||||
setElementPreservesPitch(output.element, nextRates.preservePitch);
|
||||
const nextPlaybackRate = nextRates.playbackRate;
|
||||
if (Math.abs(output.element.playbackRate - nextPlaybackRate) > 0.001) {
|
||||
output.element.playbackRate = nextPlaybackRate;
|
||||
const absCurrentRate = Math.abs(output.element.playbackRate);
|
||||
const shouldReverse = nextRates.reverse;
|
||||
const isReverseNow = output.element.playbackRate < 0;
|
||||
if (Math.abs(absCurrentRate - nextPlaybackRate) > 0.001 || isReverseNow !== shouldReverse) {
|
||||
setElementPlaybackRate(output.element, nextPlaybackRate, shouldReverse);
|
||||
}
|
||||
const spatialConfig = this.getSpatialConfig(item);
|
||||
const mix = resolveSpatialMix({
|
||||
|
||||
Reference in New Issue
Block a user