Skip to content

Commit

Permalink
🐛 [Earwurm] Various bug fixes (#50)
Browse files Browse the repository at this point in the history
  • Loading branch information
beefchimi authored Jan 4, 2024
1 parent 0bfe217 commit 51368fd
Show file tree
Hide file tree
Showing 25 changed files with 2,051 additions and 1,268 deletions.
21 changes: 21 additions & 0 deletions .changeset/seven-taxis-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
'earwurm': minor
---

Fix issue "stopping" a `Sound` that was never "started".
Include a `neverStarted: boolean;` property in the `SoundEndedEvent`.
New `volume` change event for `Earwurm`, `Stack`, and `Sound`.
New `mute` change event for `Earwurm`, `Stack`, and `Sound`.
New `library` change event for `Earwurm`.
New `queue` change event for `Stack`.
New `speed` change event for `Sound`.
`speed` Setter now clamps the value between `0.25` and `4`.
New `progress` change event.
New `progress` Getter.
New `state > ending` value.
Renamed all `statechange` events to `state`.
No longer setting `mute = false` when "pausing".
Avoid re-initializing an existing `Stack` when `.add()` is passed an identical `id + path`.
Removed `LibraryKeys` type, instead using `StackIds[]` directly.
Now exporting `tokens` object with some usual values.
Updated `docs/api.md` to include details on all the newly added / changed code.
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"editor.codeActionsOnSave": {
"source.fixAll": true
"source.fixAll": "explicit"
},
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# earwurm
# Earwurm Changelog

## 0.5.2

Expand Down
9 changes: 9 additions & 0 deletions MIGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Earwurm migration guide

## 0.6.0

For more details on the released changes, please see [🐛 Various bug fixes](https://github.com/beefchimi/earwurm/pull/50).

- Rename all instances of `statechange` to `state`.
- Example: `manager.on('statechange', () => {})`
- Replace any instances of `LibraryKeys` with the equivalent `StackIds[]`.
63 changes: 56 additions & 7 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,21 @@ manager.activeEvents;
// Returns the current `AudioContext > state`. This may trigger
// immediately upon `new Earwurm()` if the `AudioContext` is
// “unlocked” right away.
(event: 'statechange', listener: (state: ManagerState) => void)
(event: 'state', listener: (current: ManagerState) => void)

// Event called whenever the `keys` property changes. This is useful
// to subscribe to changes in the internal “stack library”.
(event: 'library', listener: (newKeys: StackId[], oldKeys: StackId[]) => void)

// Event called whenever the `volume` property changes.
(event: 'volume', listener: (level: number) => void)

// Event called whenever the `mute` property changes.
(event: 'mute', listener: (muted: boolean) => void)

// Event called whenever an error is occured on the `AudioContext`.
// This could be a result of: failed to resume, failed to close.
(event: 'error', listener: (error: CombinedErrorMessage) => void)
(event: 'error', listener: (messages: CombinedErrorMessage) => void)
```

**Static members:**
Expand Down Expand Up @@ -228,7 +238,17 @@ soundStack.activeEvents;
// the `Stack`. As sounds cycle through their various states, the
// `Stack` will determine if any `Sound` is currently `playing`.
// Possible `StackState` values are: `idle`, `loading`, `playing`.
(event: 'statechange', listener: (state: StackState) => void)
(event: 'state', listener: (current: StackState) => void)

// Event called whenever the `keys` property changes. This is useful
// to subscribe to changes in the internal “sound queue”.
(event: 'queue', listener: (newKeys: SoundId[], oldKeys: SoundId[]) => void)

// Event called whenever the `volume` property changes.
(event: 'volume', listener: (level: number) => void)

// Event called whenever the `mute` property changes.
(event: 'mute', listener: (muted: boolean) => void)

// Event called whenever an error is occured on the `Stack`.
// This could be a result of: failed to load the `path`.
Expand Down Expand Up @@ -288,6 +308,11 @@ sound.volume = 1;
// Mute / unmute this `Sound`.
sound.mute = true || false;

// Set the `playbackRate` for this `Sound.
// This value is a number used to multiply the speed of playback.
// Default is `1`. Min is `0.25`. Max is `4`.
sound.speed;

// Toggle the “repetition” of the `Sound`. Will
// repeat indefinitely if `true`, preventing the
// `ended` event from firing.
Expand All @@ -303,31 +328,55 @@ sound.volume;
// Get a `boolean` for whether or not this `Sound` is “mute”.
sound.mute;

// Get the current `playbackRate` for this `Sound.
sound.speed;

// Get a `boolean` for whether or not this `Sound` is
// to repeat indefinitely.
sound.loop;

// Get the “total play time” for this `Sound`.
sound.duration;

// Get the current `SoundProgressEvent` for this `Sound.
sound.progress;

// Get the current `state` for this `Sound`. Can be:
// `created`, `playing`, `paused`, or `stopping`.
sound.duration;
// `created`, `playing`, `paused`, `stopping`, or `ending`.
sound.state;

// Get an array of all the events for this instance
// that currently have listeners attached.
sound.activeEvents;
```

**Events:**

```ts
// Event called whenever `Sound > state` is changed.
// Possible `SoundState` values are:
// `created`, `playing`, `paused`, and `stopping`.
(event: 'statechange', listener: (state: SoundState) => void)
// `created`, `playing`, `paused`, `stopping`, and `ending`.
(event: 'state', listener: (current: SoundState) => void)

// Event called on the audio `source` node whenenver
// a `Sound` reaches either it’s “end duration”,
// or has been stopped / removed from the `Stack`.
// This will NOT get called each time a “loop” repeats.
(event: 'ended', listener: ({id, source}: SoundEndedEvent) => void)

// Event called whenever the `volume` property changes.
(event: 'volume', listener: (level: number) => void)

// Event called whenever the `mute` property changes.
(event: 'mute', listener: (muted: boolean) => void)

// Event called for every animation frame while `playing`.
// Returns data representing:
// elapsed: “seconds” into the current iteration of this `Sound`.
// remaining: “seconds” until the end of the current iteration of this `Sound`.
// percentage: “percentage progressed” into the current iteration of this `Sound`.
// iterations: number of times this `Sound` has looped.
(event: 'progress', listener: ({elapsed, remaining, percentage, iterations}: SoundProgressEvent) => void)
```

## Events API
Expand Down
6 changes: 3 additions & 3 deletions docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,14 @@ setTimeout(() => appleSound?.play(), appleSoundDuration + durationBuffer);

**Determining state values:**

While there is a dedicated `playing` property, you can obtain a more granular `state` by listening for the `statechange` event and checking the `state` property directly.
While there is a dedicated `playing` property, you can obtain a more granular `state` by listening for the `state` event and checking the `state` property directly.

```ts
let capturedState = sound.state;
let isPaused = capturedState === 'paused';

sound.on('statechange', (state) => {
capturedState = sound.state;
sound.on('state', (state) => {
capturedState = state;
isPaused = capturedState === 'paused';
});
```
Expand Down
Loading

0 comments on commit 51368fd

Please sign in to comment.