Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions src/components/canvas/players/audio-player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class AudioPlayer extends Player {
private audioResource: howler.Howl | null;
private isPlaying: boolean;

private volumeKeyframeBuilder!: KeyframeBuilder;
private volumeKeyframeBuilder: KeyframeBuilder | undefined;

private syncTimer: number;

Expand Down Expand Up @@ -45,8 +45,7 @@ export class AudioPlayer extends Player {
this.audioResource = audioResource;

// Create volume keyframes after timing is resolved (not in constructor)
const baseVolume = typeof audioClipConfiguration.volume === "number" ? audioClipConfiguration.volume : 1;
this.volumeKeyframeBuilder = new KeyframeBuilder(this.createVolumeKeyframes(audioClipConfiguration, baseVolume), this.getLength(), baseVolume);
this.rebuildVolumeKeyframeBuilder();

// Set initial volume immediately so the Howl never sits at the default of 1.0
this.audioResource.volume(this.getVolume());
Expand Down Expand Up @@ -115,6 +114,7 @@ export class AudioPlayer extends Player {
this.audioResource.unload();
}
this.audioResource = null;
this.volumeKeyframeBuilder = undefined;

super.dispose();
}
Expand Down Expand Up @@ -142,23 +142,26 @@ export class AudioPlayer extends Player {
}

this.audioResource = audioResource;
this.rebuildVolumeKeyframeBuilder();
this.audioResource.volume(this.getVolume());
}

public override reconfigureAfterRestore(): void {
super.reconfigureAfterRestore();

// Rebuild volume keyframes with updated timing
const audioAsset = this.clipConfiguration.asset as AudioAsset;
const baseVolume = typeof audioAsset.volume === "number" ? audioAsset.volume : 1;
this.volumeKeyframeBuilder = new KeyframeBuilder(this.createVolumeKeyframes(audioAsset, baseVolume), this.getLength(), baseVolume);
this.rebuildVolumeKeyframeBuilder();
}

public override getSize(): Size {
return { width: 0, height: 0 };
}

public getVolume(): number {
// A failed keyframe build can leave loaded audio available to the ticker.
if (!this.volumeKeyframeBuilder) {
return this.getBaseVolume();
}
return this.volumeKeyframeBuilder.getValue(this.getPlaybackTime());
}

Expand All @@ -173,6 +176,17 @@ export class AudioPlayer extends Player {
return Math.abs((this.audioResource.seek() as number) - this.getSourceTime());
}

private getBaseVolume(): number {
const audioAsset = this.clipConfiguration.asset as AudioAsset;
return typeof audioAsset.volume === "number" ? audioAsset.volume : 1;
}

private rebuildVolumeKeyframeBuilder(): void {
const audioAsset = this.clipConfiguration.asset as AudioAsset;
const baseVolume = this.getBaseVolume();
this.volumeKeyframeBuilder = new KeyframeBuilder(this.createVolumeKeyframes(audioAsset, baseVolume), this.getLength(), baseVolume);
}

private createVolumeKeyframes(asset: AudioAsset, baseVolume: number): Keyframe[] | number {
const { effect, volume } = asset;

Expand Down
Loading