addEventListener
Listen for one kind of event on the hub's event bus. Every sound dispatches through the same bus, so the optional filter narrows it down to the sound you care about.
addEventListener(type: SoundEventsEnum, callback: (event: SoundEvent) => void, filter?: SoundEventFilter): () => void;
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
type | SoundEventsEnum | required | The event to listen for. See soundEvents for the full list. |
callback | (event: SoundEvent) => void | required | Called for every matching event. |
filter | SoundEventFilter | none | Narrows which sounds the callback hears. Left out, it hears every sound. |
SoundEventFilter
All fields are optional and combine with AND.
| Property | Type | Description |
|---|---|---|
soundId | string | Exactly this sound. The common case. |
originalId | string | Every overlapping instance of one sound, played with overlap. |
instanceId | string | One specific instance. |
instancePattern | RegExp | Instances whose id matches a pattern. |
Returns
() => void: a function that removes this listener. That is easier to hold on to than keeping the same callback and filter around for removeEventListener.
Example
import { SoundHub, SoundEventsEnum } from 'soundhub';
const soundHub = new SoundHub();
await soundHub.loadSound('music', '/audio/theme.mp3');
// Every sound, every start
soundHub.addEventListener(SoundEventsEnum.STARTED, (event) => {
console.log('started:', event.soundId);
});
// Just this one, with no id check in the callback
soundHub.addEventListener(SoundEventsEnum.PROGRESS, (event) => {
progressBar.value = event.progressInfo!.progress;
}, { soundId: 'music' });
soundHub.play('music', { trackProgress: true });
Removing a listener
const off = soundHub.addEventListener(SoundEventsEnum.VOLUME_CHANGED, (event) => {
volumeLabel.textContent = `${Math.round(event.volume! * 100)}%`;
}, { soundId: 'music' });
// Later, on unmount or when the panel closes
off();
Every instance of one sound
Sounds played with overlap get their own ids (laser:1, laser:2, and so on), and their events carry the base id as originalId:
await soundHub.loadSound('laser', '/audio/laser.mp3');
let activeLasers = 0;
soundHub.addEventListener(SoundEventsEnum.STARTED, () => {
activeLasers += 1;
}, { originalId: 'laser' });
soundHub.addEventListener(SoundEventsEnum.ENDED, () => {
activeLasers -= 1;
}, { originalId: 'laser' });
soundHub.play('laser', { overlap: true });
soundHub.play('laser', { overlap: true });
Good to know
- Reach for
soundIdfirst. Only thestarted,endedandprogressevents carryoriginalIdandinstanceId, so a filter on those fields never hears events such asstopped,pausedorvolume_changed. instancePatternis only tested when the event has aninstanceId. An event without one gets through the pattern.- A listener with an
instanceIdfilter is removed automatically when that sound or instance stops, ends or is cleaned up. Theendedevent still reaches it first. - An error thrown inside your callback is caught and logged to the console, so the other listeners still run.
SoundEventFilteris exported from the package, as isSoundEventsEnum.
See also
once: listen for a single event.removeEventListener: remove a listener by callback and filter.soundEvents: every event type and what it carries.