import { describe, expect, test } from "bun:test"; import { dBToLinear, getTrackVolume, resolveEffectiveAudioGain, } from "@/timeline/audio-state"; import type { AudioElement, AudioTrack } from "@/timeline"; import { ZERO_MEDIA_TIME } from "@/wasm"; function audioElement(params?: AudioElement["params"]): AudioElement { return { id: "audio-1", name: "Audio", type: "audio", sourceType: "upload", mediaId: "media-1", duration: ZERO_MEDIA_TIME, startTime: ZERO_MEDIA_TIME, trimStart: ZERO_MEDIA_TIME, trimEnd: ZERO_MEDIA_TIME, params: params ?? { volume: 0, muted: false }, }; } describe("audio state", () => { test("track volume offsets element gain in decibels", () => { const gain = resolveEffectiveAudioGain({ element: audioElement({ volume: -6, muted: false }), trackVolume: -6, localTime: 0, }); expect(gain).toBeCloseTo(dBToLinear(-12), 6); }); test("track volume and mute resolve to playback gain", () => { const element = audioElement({ volume: 0, muted: false }); expect( resolveEffectiveAudioGain({ element, trackVolume: 0, localTime: 0 }), ).toBe(1); expect( resolveEffectiveAudioGain({ element, trackVolume: -6, localTime: 0 }), ).toBeCloseTo(dBToLinear(-6), 6); expect( resolveEffectiveAudioGain({ element, trackMuted: true, trackVolume: 0, localTime: 0, }), ).toBe(0); }); test("missing track volume defaults to unity", () => { const track: AudioTrack = { id: "track-1", name: "Audio track", type: "audio", elements: [], muted: false, }; expect(getTrackVolume({ track })).toBe(0); }); });