Skip to content

@gameable/audio ​

Interfaces ​

AudioBuses ​

The bus gain nodes, keyed by name.

Properties ​

master ​
ts
readonly master: GainNode;

Sums sfx, music and voice; connected to context.destination.

music ​
ts
readonly music: GainNode;

Music beds.

sfx ​
ts
readonly sfx: GainNode;

One-shot gameplay sounds.

voice ​
ts
readonly voice: GainNode;

Dialogue and say lines.


AudioEngine ​

The audio service: everything the host needs to run a frame of sound.

Properties ​

buses ​
ts
readonly buses: AudioBuses;

The bus gain nodes. Adjust bus.gain.value for mixer sliders.

context ​
ts
readonly context: AudioContext;

The context the graph lives on.

ended ​
ts
readonly ended: number[];

Handles of sounds that ended naturally or were stolen since the host last cleared this array. AudioEngine.update appends to it; the host turns each entry into a sound-ended event and then clears it with ended.length = 0.

A voice the game stopped itself — AudioEngine.stop, or a AudioEngine.play reusing a live handle — is not listed: the game already knows, and reporting it would claim a completion that never happened. Capped at 256 entries so a host that never drains it cannot grow the array without bound.

music ​
ts
readonly music: MusicPlayer;

The music player: streamed tracks, playlists, stems and the beat clock.

Methods ​

decode() ​
ts
decode(id, data): Promise<AudioBuffer>;

Decode encoded audio bytes, memoised by id.

Parameters ​
ParameterTypeDescription
idstringManifest asset id, the cache key.
dataArrayBufferEncoded bytes.
Returns ​

Promise<AudioBuffer>

The decoded buffer. Repeat calls with the same id share a promise.

dispose() ​
ts
dispose(): void;

Stop everything, drop the graph, and close a context this engine created.

Returns ​

void

play() ​
ts
play(args): void;

Start a voice, silently dropping requests rejected by concurrency limits.

Parameters ​
ParameterTypeDescription
argsPlayArgsWhat to play, where and how loud.
Returns ​

void

resume() ​
ts
resume(): Promise<void>;

Resume a context the browser suspended. Safe to call repeatedly.

Returns ​

Promise<void>

Resolves once the context is running.

setBusFx() ​
ts
setBusFx(
   bus, 
   fx, 
   fadeMs?
): void;

Set a bus's effects: a preset plus optional overrides. The chain is built on first use and only re-parameterised after that.

Parameters ​
ParameterTypeDescription
busBusNameThe bus.
fxBusFxPreset and overrides.
fadeMs?numberRamp from the current setting, in milliseconds.
Returns ​

void

setListener() ​
ts
setListener(pos, rotQuat): void;

Move the listener.

Parameters ​
ParameterTypeDescription
posVec3World position.
rotQuatQuatOrientation; forward is local -Z, up is local +Y.
Returns ​

void

setOcclusion() ​
ts
setOcclusion(
   id, 
   amount, 
   fadeMs?
): void;

How occluded a positioned voice is: 0 clear, 1 behind a wall. Lowers its low-pass cutoff and its gain.

Parameters ​
ParameterTypeDescription
idnumberThe sound handle. Unknown and non-positioned ids are ignored.
amountnumber0..1.
fadeMs?numberRamp length, in milliseconds.
Returns ​

void

setVolume() ​
ts
setVolume(id, v): void;

Change a playing voice's gain.

Parameters ​
ParameterTypeDescription
idnumberThe sound handle. Unknown ids are ignored.
vnumberLinear gain, 0..1.
Returns ​

void

stats() ​
ts
stats(): object;

Current admitted voices (including reserved), reserved voices, and lifetime drop/steal totals. Fade tails are excluded. The returned snapshot is safe for callers to retain.

Returns ​

object

dropped ​
ts
dropped: number;
reserved ​
ts
reserved: number;
stolen ​
ts
stolen: number;
voices ​
ts
voices: number;
Example ​
ts
import { createAudioEngine } from 'gameable/audio';
const engine = createAudioEngine();
console.log(engine.stats().dropped);
stop() ​
ts
stop(id, fadeMs?): void;

Stop a voice, optionally fading it out. Nothing is added to AudioEngine.ended: the caller asked for this, so it is not a completion.

Parameters ​
ParameterTypeDescription
idnumberThe handle passed to AudioEngine.play. Unknown ids are ignored.
fadeMs?numberFade-out before the stop, in milliseconds. 0 (the default) cuts.
Returns ​

void

update() ​
ts
update(): void;

Retire every voice whose buffer has run out and drain them into ended.

Timing comes from context.currentTime, the clock the voices themselves run on, not from the caller's frame delta: a long frame, a background tab or a timeScale change cannot drift the two apart. A suspended context does not advance, and neither does playback, so nothing ends early.

Returns ​

void


AudioEngineOptions ​

Options for createAudioEngine.

Extends ​

  • ConcurrencyOptions

Extended by ​

Properties ​

concurrency? ​
ts
optional concurrency?: Record<string, {
  max: number;
  retriggerMs?: number;
  rule?: "stopOldest" | "preventNew" | "stopQuietest" | "stopFarthest";
}>;

Per-group limits; missing groups use max 4, stopOldest, and a 30 ms retrigger delay.

Inherited from ​
ts
ConcurrencyOptions.concurrency
context? ​
ts
optional context?: AudioContext;

An existing context to drive. When omitted a new AudioContext is constructed, which requires a DOM environment. Pass one in tests.

distanceLowpass? ​
ts
optional distanceLowpass?: false | Partial<DistanceLowpass>;

The low-pass every positioned voice gets with distance, or false for none. Defaults to DEFAULT_DISTANCE_LOWPASS (8 m, 80 m, 2.5 kHz).

masterVolume? ​
ts
optional masterVolume?: number;

Linear gain on the master bus, 0..1. Defaults to 1.

maxVoices? ​
ts
optional maxVoices?: number;

Maximum admitted non-reserved voices. Defaults to 32; fade tails are excluded.

Inherited from ​
ts
ConcurrencyOptions.maxVoices
music? ​
ts
optional music?: MusicPlayerOptions;

Options for the music player (engine.music).

reservedBuses? ​
ts
optional reservedBuses?: string[];

Protected buses, excluded from maxVoices. Defaults to music and dialogue (voice).

Inherited from ​
ts
ConcurrencyOptions.reservedBuses

AudioModule ​

The 'audio' module. Its service is the AudioEngine it owns.

Extends ​

Properties ​

id ​
ts
readonly id: string;

Unique id. Also the service id when init returns a service.

Inherited from ​

EngineModule.id

order? ​
ts
readonly optional order?: number;

Sort key. Lower runs first; equal keys keep registration order.

Rough convention: input -100, gameplay -50, physics 0, rendering helpers 200. Gameplay runs before physics so that the commands a guest tick emits are simulated by the step that follows rather than the next one.

Inherited from ​

EngineModule.order

service ​
ts
readonly service: AudioEngine | null;

The audio engine this module owns, or null before init and after dispose.

The engine is built by init, not by audio: constructing an AudioContext is a side effect on the page — browsers count them, and an unlocked one logs a warning — so a module that is never registered must never make one. init returns the engine, so the registry publishes it under 'audio' and engine.get('audio') hands back this same object.

unlock ​
ts
readonly unlock: AudioUnlock | null;

The phone unlock, once init has armed it: unlock() from a gesture handler of your own, running for whether sound can play now.

Methods ​

beginFrame()? ​
ts
optional beginFrame(): void;

Run before the frame's fixed steps. Input capture lives here.

Returns ​

void

Inherited from ​

EngineModule.beginFrame

decodeAsset() ​
ts
decodeAsset(idOrHandle): Promise<AudioBuffer>;

Decode the bytes behind an asset id or handle, memoised.

This is the bridge from a play-sound command — which carries an asset handle, never a URL — to the AudioBuffer AudioEngine.play wants. Declared type: 'audio' entries load on demand as an ArrayBuffer before decoding. Concurrent requests share one load and decode.

Parameters ​
ParameterTypeDescription
idOrHandlestring | numberManifest asset id, or the handle the guest minted for it.
Returns ​

Promise<AudioBuffer>

The decoded buffer; rejects when the asset is missing or not audio.

decodedAsset() ​
ts
decodedAsset(idOrHandle): AudioBuffer | undefined;

The already-decoded buffer for an asset, without awaiting anything.

This is what lets the host play a repeated sound — a footstep, a shot — inside the frame that asked for it instead of a microtask later. A miss means "not decoded yet"; fall back to AudioModule.decodeAsset.

Handles and ids share one cache entry: a handle is normalised through the asset registry first, so decodedAsset(7) and decodedAsset('sfx.shot') hit the same buffer.

Parameters ​
ParameterTypeDescription
idOrHandlestring | numberManifest asset id, or the handle the guest minted for it.
Returns ​

AudioBuffer | undefined

The decoded buffer, or undefined when no decode has finished.

dispose() ​
ts
dispose(): void;

Release everything this module took.

Returns ​

void

Inherited from ​

EngineModule.dispose

endFrame()? ​
ts
optional endFrame(): void;

Run after rendering. Input's end-of-frame bookkeeping lives here.

Returns ​

void

Inherited from ​

EngineModule.endFrame

fixedUpdate()? ​
ts
optional fixedUpdate(dt): void;

Run once per fixed step.

Parameters ​
ParameterTypeDescription
dtnumberAlways ctx.config.fixedDt, whatever time.timeScale is; time scale changes how many steps a frame runs, not their length.
Returns ​

void

Inherited from ​

EngineModule.fixedUpdate

init() ​
ts
init(ctx): AudioEngine;

Build the engine and publish it as the 'audio' service.

Parameters ​
ParameterTypeDescription
ctxHostContextThe host surface; only ctx.assets is read.
Returns ​

AudioEngine

The audio engine.

Overrides ​

EngineModule.init

update() ​
ts
update(dt, alpha): void;

Pump the engine: retire finished voices and fill service.ended. A no-op before init.

Always present on this module, so callers need no optional call.

Parameters ​
ParameterTypeDescription
dtnumberWall-clock seconds since the previous frame; unused, because the engine times voices on the audio context's own clock.
alphanumberInterpolation factor; unused by audio.
Returns ​

void

Overrides ​

EngineModule.update


AudioModuleOptions ​

Options for audio.

Extends ​

Properties ​

concurrency? ​
ts
optional concurrency?: Record<string, {
  max: number;
  retriggerMs?: number;
  rule?: "stopOldest" | "preventNew" | "stopQuietest" | "stopFarthest";
}>;

Per-group limits; missing groups use max 4, stopOldest, and a 30 ms retrigger delay.

Inherited from ​

AudioEngineOptions.concurrency

context? ​
ts
optional context?: AudioContext;

An existing context to drive. When omitted a new AudioContext is constructed, which requires a DOM environment. Pass one in tests.

Inherited from ​

AudioEngineOptions.context

distanceLowpass? ​
ts
optional distanceLowpass?: false | Partial<DistanceLowpass>;

The low-pass every positioned voice gets with distance, or false for none. Defaults to DEFAULT_DISTANCE_LOWPASS (8 m, 80 m, 2.5 kHz).

Inherited from ​

AudioEngineOptions.distanceLowpass

masterVolume? ​
ts
optional masterVolume?: number;

Linear gain on the master bus, 0..1. Defaults to 1.

Inherited from ​

AudioEngineOptions.masterVolume

maxVoices? ​
ts
optional maxVoices?: number;

Maximum admitted non-reserved voices. Defaults to 32; fade tails are excluded.

Inherited from ​

AudioEngineOptions.maxVoices

music? ​
ts
optional music?: MusicPlayerOptions;

Options for the music player (engine.music).

Inherited from ​

AudioEngineOptions.music

order? ​
ts
optional order?: number;

Position in the module order. Lower runs first. Defaults to 30.

reservedBuses? ​
ts
optional reservedBuses?: string[];

Protected buses, excluded from maxVoices. Defaults to music and dialogue (voice).

Inherited from ​

AudioEngineOptions.reservedBuses

unlock? ​
ts
optional unlock?: Omit<AudioUnlockOptions, "target">;

The phone unlock's settings (unlock.ts): play as media under the silent switch, the silent loop for older phones, a change listener. Defaults on.

unlockTarget? ​
ts
optional unlockTarget?: EventTarget;

Where the unlock listeners are installed. Defaults to the global object; pass the canvas to scope it, or a stub in tests.


AudioUnlock ​

The unlock.

Properties ​

running ​
ts
readonly running: boolean;

The context can make sound right now.

Methods ​

dispose() ​
ts
dispose(): void;

Remove the listeners and stop the silent loop.

Returns ​

void

unlock() ​
ts
unlock(): void;

Do everything a tap allows, now: the session type, the silent loop, the resume, a silent sample. Call it from your own gesture handler if you have one; the listeners call it for you.

Returns ​

void


AudioUnlockOptions ​

Options for createAudioUnlock.

Properties ​

keepAlive? ​
ts
optional keepAlive?: boolean;

On a phone with no audioSession setting (an older iPhone), keep the output open with a silent looping <audio> element. Default true.

ts
optional navigator?: Navigator;

The navigator to read the session and the device from; the global one by default.

onChange? ​
ts
optional onChange?: (running) => void;

Told each time the context's state changes.

Parameters ​
ParameterType
runningboolean
Returns ​

void

onGesture? ​
ts
optional onGesture?: () => void;

Called synchronously on every gesture, including while the context is running.

Returns ​

void

playback? ​
ts
optional playback?: boolean;

Play the page as media, so a phone's ring/silent switch does not mute it (navigator.audioSession.type = 'playback'). Default true; false for a page that records the microphone and wants the call-style session.

target? ​
ts
optional target?: EventTarget;

Where the first-touch listeners go. Defaults to the global window, so a tap anywhere on the page (a button, the canvas, the talk panel) counts.


BeatGrid ​

A track's beat grid.

Properties ​

beatsPerBar? ​
ts
optional beatsPerBar?: number;

Beats in a bar. Defaults to 4.

bpm ​
ts
bpm: number;

Beats per minute. 0 or less: no grid.

firstBeat? ​
ts
optional firstBeat?: number;

Seconds from the start of the file to beat 0. Defaults to 0.


BeatTick ​

A beat the player heard, as drained by MusicPlayer.drain. Pooled: do not keep it.

Properties ​

bar ​
ts
bar: number;

Bar number, from 0.

beat ​
ts
beat: number;

Beat number since the music started, from 0.

beatInBar ​
ts
beatInBar: number;

Beat within the bar, from 0.

lateMs ​
ts
lateMs: number;

How long ago the beat was heard, in milliseconds (0 or more).


BusFx ​

One bus's effect setting: a preset, and optional fields that override that preset's own value for this call.

Properties ​

compressor? ​
ts
optional compressor?: boolean;

Whether the bus runs through a compressor.

highpassHz? ​
ts
optional highpassHz?: number;

High-pass cutoff in Hz. 10 or less is off.

lowpassHz? ​
ts
optional lowpassHz?: number;

Low-pass cutoff in Hz. 22000 or more is off.

preset? ​
ts
optional preset?: FxPreset;

The base setting. Defaults to 'dry'.

reverb? ​
ts
optional reverb?: number;

Reverb wet level, 0..1. 0 is no reverb.


DistanceLowpass ​

The distance low-pass curve applied to every positioned voice.

Properties ​

far ​
ts
far: number;

Metres at which the cutoff reaches minHz. Default 80.

minHz ​
ts
minHz: number;

Cutoff at and beyond far, in Hz. Default 2500.

near ​
ts
near: number;

Metres up to which the voice is unfiltered. Default 8.


MusicPlayer ​

The music service, engine.music.

Properties ​

blocked ​
ts
readonly blocked: boolean;

True when the browser refused play() outside a gesture; the next gesture retries.

grid ​
ts
readonly grid: Readonly<Required<BeatGrid>> | undefined;

The current grid, or undefined when the music has none.

playing ​
ts
readonly playing: boolean;

True while a track or stem set is playing (or fading in).

Methods ​

dispose() ​
ts
dispose(): void;

Stop and release the decks.

Returns ​

void

drain() ​
ts
drain(onBeat, onTrack): void;

Hand the beats and track starts since the last drain to the host, then forget them.

Parameters ​
ParameterTypeDescription
onBeat(tick) => voidCalled once per beat heard (at most 16 per drain), oldest first.
onTrack(index) => voidCalled with the index of each track that started.
Returns ​

void

nextGridTime() ​
ts
nextGridTime(quantize, subdivision?): number | undefined;

The context time of the next grid point after now (+10 ms of lead).

Parameters ​
ParameterTypeDescription
quantizeQuantize'beat' or 'bar'; 'now' returns context.currentTime.
subdivision?numberGrid points per beat for 'beat'. Defaults to 1.
Returns ​

number | undefined

Context seconds, or undefined when the music has no grid.

play() ​
ts
play(args): void;

Start music, crossfading from what is playing.

Parameters ​
ParameterTypeDescription
argsPlayMusicArgsWhat to play and how.
Returns ​

void

prime() ​
ts
prime(): void;

Call synchronously inside a user gesture: unlocks the deck elements on phones and retries a blocked play().

Returns ​

void

setLayer() ​
ts
setLayer(
   index, 
   gain, 
   fadeMs?
): void;

Change one stem's gain.

Parameters ​
ParameterTypeDescription
indexnumberStem index in the stems passed to play.
gainnumberLinear gain, 0..1.
fadeMs?numberRamp length; 0 sets it now.
Returns ​

void

stop() ​
ts
stop(fadeMs?): void;

Fade the music out and stop it.

Parameters ​
ParameterTypeDescription
fadeMs?numberFade length; 0 cuts.
Returns ​

void

update() ​
ts
update(): void;

Advance crossfades, playlists, drift correction and the beat clock. Allocation-free.

Returns ​

void


MusicPlayerOptions ​

Options for the music player.

Properties ​

createMediaElement? ​
ts
optional createMediaElement?: () => HTMLAudioElement;

Build a media element for a deck. Defaults to document.createElement('audio').

Returns ​

HTMLAudioElement


PlayArgs ​

One call to AudioEngine.play.

Properties ​

buffer ​
ts
buffer: AudioBuffer;

The decoded buffer to play, normally from AudioEngine.decode.

bus? ​
ts
optional bus?: "dialogue" | BusName;

Bus to route through. Defaults to 'sfx'; 'dialogue' aliases 'voice'.

group? ​
ts
optional group?: string;

Concurrency group. Defaults to the decoded asset id, otherwise this call's id.

id ​
ts
id: number;

Guest-minted sound handle. Replaces any sound already using this handle.

loop? ​
ts
optional loop?: boolean;

Loop until stopped. Looping voices never end on their own. Defaults to false.

pitch? ​
ts
optional pitch?: number;

Playback-rate multiplier; also scales the natural end time. Defaults to 1.

pos? ​
ts
optional pos?: Vec3;

World position. When given the voice gets an HRTF PannerNode.

volume? ​
ts
optional volume?: number;

Linear gain, 0..1. Defaults to 1.

when? ​
ts
optional when?: number;

Context time (seconds, context.currentTime clock) to start at, for a sample-accurate scheduled start. Past times start now. Defaults to now.


PlayMusicArgs ​

One MusicPlayer.play.

Properties ​

fadeMs? ​
ts
optional fadeMs?: number;

Crossfade from whatever is playing, in milliseconds. Defaults to 0 (a cut).

grid? ​
ts
optional grid?: BeatGrid;

The beat grid of every track (or of the stems). Omit for no beat clock.

loop? ​
ts
optional loop?: boolean;

Loop the track, the playlist or the stems. Defaults to false.

start? ​
ts
optional start?: Quantize;

Start now, or on the current music's next beat or bar. Defaults to 'now'.

stemGains? ​
ts
optional stemGains?: readonly number[];

Initial gain per stem, 0..1; missing entries are 1.

stems? ​
ts
optional stems?: readonly AudioBuffer[];

Decoded, sample-locked layers, all started with one start(when).

tracks? ​
ts
optional tracks?: readonly StreamedTrack[];

Streamed tracks in order; more than one is a playlist. Ignored when stems is non-empty.

volume? ​
ts
optional volume?: number;

Linear gain, 0..1. Defaults to 1.


StreamedTrack ​

A track the player streams through a media element.

Properties ​

url ​
ts
url: string;

Resolved URL. Game code never sees it: the module resolves asset ids.

Type Aliases ​

BusName ​

ts
type BusName = "master" | "sfx" | "music" | "voice";

The buses a voice can be routed to. master is the sum of the other three.


FxPreset ​

ts
type FxPreset = 
  | "dry"
  | "room"
  | "hall"
  | "cave"
  | "underwater"
  | "radio"
  | "muffled"
  | "arena";

A named bus-effect setting. dry is every stage transparent.


Quantize ​

ts
type Quantize = "now" | "beat" | "bar";

When something starts relative to the current music's grid.


Quat ​

ts
type Quat = readonly [number, number, number, number];

A rotation, as a plain [x, y, z, w] quaternion (three.js / Jolt order).


Vec3 ​

ts
type Vec3 = readonly [number, number, number];

A world-space position, as a plain [x, y, z] array.

Variables ​

DEFAULT_DISTANCE_LOWPASS ​

ts
const DEFAULT_DISTANCE_LOWPASS: Readonly<DistanceLowpass>;

The default distance curve.


FX_PRESETS ​

ts
const FX_PRESETS: readonly FxPreset[];

Every preset name, in a fixed order (the WIT fx-preset order).


PACKAGE ​

ts
const PACKAGE: "@gameable/audio";

Package identity marker.

Example ​

ts
import { PACKAGE } from 'gameable/audio';

console.log(PACKAGE); // 'gameable/audio'

Functions ​

audio() ​

ts
function audio(options?): AudioModule;

Create the audio module.

Register it in the engine's module list. init builds the AudioEngine and returns it, so it becomes the 'audio' service: the host maps play-sound / stop-sound / set-listener straight onto its methods and drains ended into sound-ended events each frame. Until then AudioModule.service is null and no AudioContext exists.

Browsers keep an AudioContext suspended until the page sees a user gesture, so init arms the phone unlock (unlock.ts): the first touch, key or click opens the output, with the session type and the silent loop a phone needs, and a context suspended again (a call, the lock screen) is opened again by the next touch.

Parameters ​

ParameterTypeDescription
optionsAudioModuleOptionsEngine options, plus the unlock target and module order.

Returns ​

AudioModule

The module, ready to register.

Example ​

ts
import { audio } from 'gameable/audio';

const mod = audio({ masterVolume: 0.8 });
const engine = mod.init(ctx);

const buffer = await mod.decodeAsset('pistol');
engine.play({ id: 1, buffer, pos: [0, 1, -3] });
mod.update(1 / 60, 0);

// The next shot needs no await: the decode has already settled.
const again = mod.decodedAsset('pistol');
if (again) engine.play({ id: 2, buffer: again });

createAudioEngine() ​

ts
function createAudioEngine(options?): AudioEngine;

Create the audio engine.

The graph is source -> gain -> [lowpass -> panner] -> bus -> [effects] -> master. Nothing is allocated per frame: voices are pooled, the listener basis is written into scratch arrays, and ended is reused.

Parameters ​

ParameterTypeDescription
optionsAudioEngineOptionsContext to adopt and initial master gain.

Returns ​

AudioEngine

The engine, which is also the 'audio' module's service.

Example ​

ts
import { createAudioEngine } from 'gameable/audio';

const engine = createAudioEngine({ masterVolume: 0.8 });
const buffer = await engine.decode('pistol', bytes);

engine.play({ id: 1, buffer, pos: [3, 0, -4], bus: 'sfx' });
engine.update();
for (const id of engine.ended) console.log('ended', id);
engine.ended.length = 0;

createAudioUnlock() ​

ts
function createAudioUnlock(context, options?): AudioUnlock;

Arm the unlock on a context: the first gesture opens the output, and every gesture after a suspension opens it again.

Parameters ​

ParameterTypeDescription
contextAudioContextThe context to unlock.
optionsAudioUnlockOptionsSee AudioUnlockOptions.

Returns ​

AudioUnlock

The unlock; dispose() when the engine shuts down.

Example ​

ts
import { createAudioUnlock } from 'gameable/audio';

const unlock = createAudioUnlock(new AudioContext(), { onChange: (on) => console.log(on) });
unlock.dispose();

createMusicPlayer() ​

ts
function createMusicPlayer(
   context, 
   output, 
   options?
): MusicPlayer;

Create the music player on a context, feeding output (the music bus).

Parameters ​

ParameterTypeDescription
contextAudioContextThe engine's context.
outputAudioNodeNode the decks connect to.
options?MusicPlayerOptionsMedia element factory.

Returns ​

MusicPlayer

The player.


isAppleTouchDevice() ​

ts
function isAppleTouchDevice(nav): boolean;

Whether this is a phone or tablet whose output needs keeping open: an iPhone or an iPad (which reports itself as a Mac with a touch screen).

Parameters ​

ParameterTypeDescription
navNavigator | undefinedThe navigator.

Returns ​

boolean

True on an iPhone, an iPod or an iPad.