Talos docs

AudioHandle

Since 0.6

Mixer control: the bus graph, its snapshots, the music layers, and one-shot cues.

Plain text

Reached in a behaviour as ctx.audio.

Signature

export interface AudioHandle {
  /** Start a sound from the scene's assets; returns a handle for `stop`. */
  play(asset: string, opts?: AudioOptions): number
  stop(handle: number): void
  /**
   * Change the playback rate of a sound that is playing, e.g. an engine loop following RPM.
   * `rate` 1 is as authored; it must be finite and above 0. With `rampSeconds` the rate glides
   * there linearly in sim time (no zipper noise) from wherever it is now; without, it steps.
   * A new call replaces a ramp in flight. A handle that has ended, was never valid, or was
   * refused by `play` (0) does nothing and does not throw, as with {@link stop}.
   * Calls apply in call order at the next sim tick.
   *
   * @since 0.6.0
   */
  setPitch(handle: number, rate: number, opts?: AudioRampOptions): void
  /**
   * Change the volume (0..1, as {@link AudioOptions.volume}) of a sound that is playing, with
   * the same ramp and no-op rules as {@link setPitch}. This is the voice's own volume; the bus
   * it plays on still applies on top.
   *
   * @since 0.6.0
   */
  setVolume(handle: number, volume: number, opts?: AudioRampOptions): void
  /** A handle onto one bus of `meta.audio.buses`. */
  bus(name: AudioBus): AudioBusHandle
  /**
   * Cross-fade every bus to a named snapshot over that snapshot's own transition time.
   * Buses the snapshot does not name go back to their authored volume, so snapshots
   * replace each other rather than stacking. False when there is no such snapshot.
   */
  snapshot(name: string): boolean
  readonly music: AudioMusicHandle
}

Import: import type { AudioHandle } from "@argus/api"

Members

MemberSignatureDescription
playplay(asset: string, opts?: AudioOptions): numberStart a sound from the scene's assets; returns a handle for stop.
stopstop(handle: number): void
setPitchsetPitch(handle: number, rate: number, opts?: AudioRampOptions): voidChange the playback rate of a sound that is playing, e.g. an engine loop following RPM. rate 1 is as authored; it must be finite and above 0. With rampSeconds the rate glides there linearly in sim time (no zipper noise) from wherever it is now; without, it steps. A new call replaces a ramp in flight. A handle that has ended, was never valid, or was refused by play (0) does nothing and does not throw, as with {@link stop}. Calls apply in call order at the next sim tick. @since 0.6.0
setVolumesetVolume(handle: number, volume: number, opts?: AudioRampOptions): voidChange the volume (0..1, as {@link AudioOptions.volume}) of a sound that is playing, with the same ramp and no-op rules as {@link setPitch}. This is the voice's own volume; the bus it plays on still applies on top. @since 0.6.0
busbus(name: AudioBus): AudioBusHandleA handle onto one bus of meta.audio.buses.
snapshotsnapshot(name: string): booleanCross-fade every bus to a named snapshot over that snapshot's own transition time. Buses the snapshot does not name go back to their authored volume, so snapshots replace each other rather than stacking. False when there is no such snapshot.
musicreadonly music: AudioMusicHandle

Example

The tested fixture fixtures/recipes/jump-pad-and-elevator/scenes/behaviors/camera-zone.ts.

import type { Behavior } from "@argus/api"

/**
 * A trigger volume that retunes the camera while the player is inside it.
 *
 * The engine has no camera-zone concept and needs none: a volume, a `trigger` component and this.
 * Here the player's behaviour owns the camera (it re-sends its params when the view is turned), so
 * the zone tells it what to change rather than calling `ctx.camera.set` itself. In a scene where
 * nothing else writes the camera, the zone can call `ctx.camera.set(kind, params)` directly.
 */
interface Props {
  /** `ctx.camera.set` params to merge in on the way in, and on the way out. */
  inside?: Record<string, unknown>
  outside?: Record<string, unknown>
}

export default {
  onTrigger(ctx, trigger) {
    const params = trigger.entering ? ctx.props.inside : ctx.props.outside
    if (params) ctx.events.emit("camera-zone", { target: trigger.other.id, params })
  },
} satisfies Behavior<Record<string, never>, Props>