SoundState
getSoundState returns a SoundStateInfo: everything a player interface needs about one sound in a single object. Its state field uses the SoundState enum.
export interface SoundStateInfo {
progress: number;
startTime: number;
currentTime: number;
elapsedTime: number;
adjustedElapsedTime: number;
duration: number;
rawDuration: number | null;
playbackRate: number | null;
state: SoundState;
volume: number;
pan: number;
panSpatialPosition: { x: number; y: number; z: number };
}
export enum SoundState {
Playing = "playing",
Paused = "paused",
Stopped = "stopped",
}
| Field | Type | Description |
|---|---|---|
progress | number | How far along the sound is, from 0 to 1. |
startTime | number | The AudioContext time the hub counts the position from, in seconds. 0 before the first play. For a stream, the start offset. |
currentTime | number | Position in the file, in seconds, whatever the playback rate. |
elapsedTime | number | Position in the file, in seconds. For a loop it equals currentTime. |
adjustedElapsedTime | number | The time it took to hear that far, at the current playback rate: elapsedTime divided by the rate. |
duration | number | Length of the file, in seconds. |
rawDuration | number | null | Length of the file itself, in seconds. |
playbackRate | number | null | The current playback rate. |
state | SoundState | 'playing', 'paused' or 'stopped'. |
volume | number | The sound's volume, 0 to 1. |
pan | number | Stereo pan, -1 (left) to 1 (right). |
panSpatialPosition | { x, y, z } | The sound's 3D position. |
SoundState is exported from soundhub as a value, SoundStateInfo as a type.
Every time is a position in the file, for buffered sounds and streams alike, as it is for an HTMLMediaElement. At double speed, half a second after the start, currentTime is 1. A position stays valid when the rate changes, and currentTime / duration is the progress. Only adjustedElapsedTime counts the time it took to hear. Before 6.4.0 a buffered sound divided currentTime, elapsedTime and duration by the rate.
Example
import { SoundHub, SoundState } from 'soundhub';
const soundHub = new SoundHub();
await soundHub.loadSound('music', '/audio/theme.mp3');
soundHub.play('music', { volume: 0.7, pan: -0.5 });
const state = soundHub.getSoundState('music');
state.state; // 'playing'
state.volume; // 0.7
state.pan; // -0.5
// A progress bar driven by the state
function render() {
const { progress, currentTime, duration, state } = soundHub.getSoundState('music');
bar.style.width = `${progress * 100}%`;
label.textContent = `${currentTime.toFixed(1)}s / ${duration.toFixed(1)}s`;
if (state === SoundState.Playing) {
requestAnimationFrame(render);
}
}
render();
Try it
Play, pause and stop the sound and watch every field of SoundStateInfo update live.
Ask a sound where it is
IdleExactly one of the three is true at any moment. The values are read five times a second.
Good to know
- For an id that is not loaded you get a neutral, stopped state instead of an error: every time is
0,volumeis the config'sdefaultVolumeandplaybackRateitsdefaultPlaybackRate. That makes it safe to call from a render loop. - The time values and
progressare rounded to 4 decimals withroundValue. - A looping sound reports where it is inside the file, so
currentTimegoes back to0at every loop. - Each overlapping instance, played with
overlap: true, has its own state under its instance id, like'click:1'.getSoundIdslists them. - For a quick yes or no,
isPlaying,isPausedandisStoppedread more clearly than comparingstate. - The full state also comes with every
progressevent, inevent.state.
See also
getSoundState: get this object for a sound.SoundProgressStateInfo: the smaller payload of aprogressevent.isPlaying: check whether a sound is playing.getCurrentTime: only the position.