,
This commit is contained in:
parent
70423851ba
commit
1fe5015056
55 changed files with 2036 additions and 685 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import type { GardenAudioEngineConfig } from '../config';
|
||||
import { clamp, clamp01 } from '../utils/clamp';
|
||||
import { ErrorHandler, Severity } from '../utils/error-handler';
|
||||
import { VibePreset } from '../vibes';
|
||||
import { GardenAudioConfig } from './garden-audio-config';
|
||||
import { GardenAudioEnergy } from './garden-audio-energy';
|
||||
|
|
@ -71,40 +72,66 @@ export class GardenAudio {
|
|||
return;
|
||||
}
|
||||
|
||||
const startupRampSeconds =
|
||||
options.userGesture === true
|
||||
? this.engineConfig.muteRampSeconds
|
||||
: this.config.fadeInSeconds;
|
||||
const needsResume = context.state !== 'running' && context.state !== 'closed';
|
||||
let resumePromise: Promise<void> | null = null;
|
||||
|
||||
if (needsResume) {
|
||||
if (options.userGesture !== true) {
|
||||
return;
|
||||
}
|
||||
resumePromise = context.resume();
|
||||
}
|
||||
|
||||
if (options.userGesture === true) {
|
||||
this.graph.unlock();
|
||||
}
|
||||
|
||||
if (context.state === 'suspended') {
|
||||
if (options.userGesture !== true) {
|
||||
return;
|
||||
}
|
||||
void context.resume().catch(() => undefined);
|
||||
if (resumePromise) {
|
||||
void resumePromise
|
||||
.then(() => {
|
||||
if (this.graph.context === context && !this.isDestroyed && !this.isMuted) {
|
||||
this.graph.unlock();
|
||||
this.graph.setMasterGain(this.config.masterVolume, startupRampSeconds);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
ErrorHandler.addException(error, {
|
||||
fallbackMessage: 'Could not resume audio playback.',
|
||||
severity: Severity.WARNING,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
this.hasStarted = true;
|
||||
this.applyVibe(vibe);
|
||||
this.pianoEngine.prime(context.currentTime);
|
||||
this.graph.setMasterGain(
|
||||
this.config.masterVolume,
|
||||
options.userGesture === true
|
||||
? this.engineConfig.muteRampSeconds
|
||||
: this.config.fadeInSeconds
|
||||
);
|
||||
this.graph.setMasterGain(this.config.masterVolume, startupRampSeconds);
|
||||
|
||||
if (!this.hasQueuedPianoLoad) {
|
||||
this.hasQueuedPianoLoad = true;
|
||||
void this.piano.load(context).then(() => {
|
||||
if (this.graph.context === context && !this.isDestroyed) {
|
||||
this.pianoEngine.cue(context.currentTime);
|
||||
}
|
||||
});
|
||||
void this.piano
|
||||
.load(context)
|
||||
.then(() => {
|
||||
if (this.graph.context === context && !this.isDestroyed) {
|
||||
this.pianoEngine.cue(context.currentTime);
|
||||
}
|
||||
})
|
||||
.catch(() => undefined);
|
||||
}
|
||||
}
|
||||
|
||||
public changeVibe(vibe: VibePreset, options: GardenAudioStartOptions = {}): void {
|
||||
const previousVibeId = this.currentVibeId;
|
||||
this.start(vibe, options);
|
||||
const didChangeVibe = previousVibeId !== null && previousVibeId !== vibe.id;
|
||||
|
||||
if (didChangeVibe) {
|
||||
this.piano.stopAll();
|
||||
}
|
||||
|
||||
const context = this.graph.context;
|
||||
if (
|
||||
|
|
@ -112,8 +139,7 @@ export class GardenAudio {
|
|||
(context.state === 'running' || options.userGesture === true) &&
|
||||
!this.isMuted &&
|
||||
!this.isDestroyed &&
|
||||
previousVibeId !== null &&
|
||||
previousVibeId !== vibe.id
|
||||
didChangeVibe
|
||||
) {
|
||||
this.playVibeChangeStinger(vibe);
|
||||
}
|
||||
|
|
@ -158,7 +184,7 @@ export class GardenAudio {
|
|||
|
||||
this.selectedColorIndex = normalizeColorIndex(touch.colorIndex);
|
||||
const mirrorAmount = this.getMirrorAmount(touch.mirrorSegmentCount ?? 1);
|
||||
const pressure = this.getTouchPressure(touch.pressure, touch.pointerType);
|
||||
const pressure = this.getPressure(touch.pressure);
|
||||
const strength = clamp01(0.36 + pressure * 0.34 + mirrorAmount * 0.22);
|
||||
const frame = this.gestureState.recordTouchDown({
|
||||
touch,
|
||||
|
|
@ -225,7 +251,6 @@ export class GardenAudio {
|
|||
const metrics = getStrokeMetrics(
|
||||
stroke,
|
||||
this.config.rhythm.speedForFullEnergyPixelsPerSecond,
|
||||
this.config.input.pressureFallback,
|
||||
this.engineConfig.input
|
||||
);
|
||||
const now = context.currentTime;
|
||||
|
|
@ -375,16 +400,11 @@ export class GardenAudio {
|
|||
return clamp01((segmentCount - 1) / (maxMirrorSegmentCount - 1));
|
||||
}
|
||||
|
||||
private getTouchPressure(pressure: number | undefined, pointerType?: string): number {
|
||||
private getPressure(pressure: number | undefined): number {
|
||||
if (pressure !== undefined && Number.isFinite(pressure) && pressure > 0) {
|
||||
return clamp01(pressure);
|
||||
}
|
||||
|
||||
return pointerType === 'pen'
|
||||
? Math.max(
|
||||
this.engineConfig.input.penMinPressure,
|
||||
this.config.input.pressureFallback
|
||||
)
|
||||
: this.config.input.pressureFallback;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue