Most roadmap tasks should be available here: https://github.com/beefchimi/earwurm/issues
While we are intentionally keeping the scope of Earwurm
to an absolute minimum, there are still some features / tasks that remain to be completed.
- Should we make
context
available to the consumer so that they can re-use it for other things?- Can cause many complications within
Earwurm
.
- Can cause many complications within
- Should we have some “SSR/node detection” to know if we can actually use the
Web Audio API
?- Can the
Web Audio API
work on a server / in node?
- Can the
- Should we offer a utility to help detect:
AudioContext
support.webm
format support.opus
codec support.
- Should we implement the “distortion fix” within the
unlock
method?Howler
uses this, but I'm not sure if its relevant for evergreen browsers.
- Consider a
autoSuspendDelay
config option.- Accepts a
ms
value that defaults to30000
. - If
0
is passed toautoSuspendDelay
, then we consider that a “opt-out” value and disable the auto-suspension.
- Accepts a
- Should we allow “restarting” a
Earwurm
instance after.teardown()
has been called?- My current preference is, once
.teardown()
is called, you are done with that instance and will not be resurrecting it. - We are not however setting
#context
andmanagerGain
tonull
, because that would introduce anull
type that I do not want to check for within the code.
- My current preference is, once
- Investigate if it makes any sense to utilize a
OfflineAudioContext
. - Consider a
delay
property for aSound
.- The idea is that the
delay
is persistent for that sound. - The
delay
is included in each subsequentloop
, instead of ONLY applying to the first iteration. - Maybe a
startPad
andendPad
make sense?
- The idea is that the
- Should we offer a way to "pre-fetch" all audio data within an
Earwurm
?- Otherwise, we will sometimes have a "delay" before audio begins playing for the first time.
- It would also be nice if a
Stack
had acached
boolean getter.
- Is it reasonable to cache the decoded
AudioBuffer
by storing it on theStack
instance?- We could introduce this private property:
#audioBuffer: AudioBuffer | null;
- And then add an option to the
config
forcacheAudioBuffer?: boolean;
- This would have to be flagged as potentially "dangerous", as I imagine caching too many buffers creates considerable overhead.
- We could introduce this private property:
- Do we need to re-check the
#queue
state when a sound hasended
?- This would be done within
Stack > #handleSoundEnded
. - A sound goes into a
stopping
state first, which will trigger#setStateFromQueue
. There shouldn't be any reason for theended
event to fail… but if so, then we will need to re-check.
- This would be done within
- Find out if
statechange
event listeners automatically get removed upon calling.close()
/ state change toclosed
on aAudioContext
.- If so, then I can remove the
.close().then()
chain.
- If so, then I can remove the
- Consider adding a
readonly parent
to bothStack
andSound
.- The value of each would be
this
from either theManager
or theStack
. - Example: This would allow me to know what
Stack
manages a particularSound
.
- The value of each would be
- Consider setting
Stack > state
toclosed
onteardown
.- This way, there is a better mechanism to removing a
Stack
after listening to astatechange
.
- This way, there is a better mechanism to removing a
Maybe there is some value in passing an array of GainNode/AudioNode
for destination
? If so, that might look something like:
export type AudioOutputs = [...GainNode[], AudioNode];
constructor(readonly outputs: AudioOutputs);
let lastConnection: GainNode | AudioNode = this.#gainNode;
outputs.forEach((node) => {
lastConnection = lastConnection.connect(node);
});