misairu 4.1.0 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/types.ts ADDED
@@ -0,0 +1,58 @@
1
+ import { Misairu } from './misairu'
2
+
3
+ /**
4
+ * Type describing the structure of the event cache
5
+ */
6
+ export type EventCache = {
7
+ [trackName: string]: string
8
+ }
9
+
10
+ /**
11
+ * Type describing the available arguments of event functions
12
+ */
13
+ export type EventFunction = (
14
+ instance: Misairu,
15
+ timingKey: string,
16
+ track: string,
17
+ time: number
18
+ ) => void
19
+
20
+ /**
21
+ * Type describing the structure of an event track
22
+ */
23
+ export type EventTrack = {
24
+ [timingKey: string]: EventFunction
25
+ }
26
+
27
+ /**
28
+ * Type describing the structure of the timing object
29
+ */
30
+ export type TimingObject = {
31
+ [trackName: string]: EventTrack
32
+ }
33
+
34
+ /**
35
+ * Interface describing required methods/members for track processors
36
+ */
37
+ export interface ITrackProcessor {
38
+ /**
39
+ * Member describing if the processed track should be deleted
40
+ */
41
+ deleteOriginTrack: boolean
42
+
43
+ /**
44
+ * Method to check if the track name matches to determine if the processor
45
+ * should process it
46
+ *
47
+ * @param name name oƒ a track
48
+ */
49
+ matches(name: string): boolean
50
+
51
+ /**
52
+ * Main processing method
53
+ *
54
+ * @param name name of the track to be processed
55
+ * @param track content of the track to be processed
56
+ */
57
+ process(name: string, track: EventTrack | EventFunction): [string, EventTrack]
58
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Method to turn the passed decibel values into volume values for the audio playback
3
+ *
4
+ * @param db decibel value
5
+ * @returns volume value
6
+ */
7
+ export function dbToVolume(db: number): number {
8
+ return Math.pow(10, db / 20)
9
+ }
10
+
11
+ /**
12
+ * Clamps the volume to a min/max value to prevent accidental oversetting to way too loud measures
13
+ */
14
+ export function clampGain(volume: number): number {
15
+ if (volume < -80) {
16
+ return -80
17
+ } else if (volume > 5) {
18
+ return 5
19
+ }
20
+
21
+ return volume
22
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Method to fetch the external audio file (if the audio source parameter was a string)
3
+ * and turning it into a `AudioBufferSourceNode`
4
+ *
5
+ * @param audioSource the audio source `Misairu` has been constructed with
6
+ * @internal
7
+ */
8
+ export async function fetchAudioSource(audioSource: string, audioContext: AudioContext): Promise<AudioBufferSourceNode> {
9
+ const source = audioContext.createBufferSource()
10
+
11
+ const response = await fetch(audioSource)
12
+ const arrayBuffer = await response.arrayBuffer()
13
+ const buffer = await audioContext.decodeAudioData(arrayBuffer)
14
+
15
+ source.buffer = buffer
16
+
17
+ return source
18
+ }
19
+
20
+ /**
21
+ * Method to get an `MediaElementAudioSourceNode` from the passed audio source
22
+ *
23
+ * @param audioSource the audio source `Misairu` has been constructed with
24
+ * @internal
25
+ */
26
+ export function attachAudioElementSource(audioSource: HTMLMediaElement, audioContext: AudioContext): MediaElementAudioSourceNode {
27
+ return audioContext.createMediaElementSource(audioSource)
28
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "suppressImplicitAnyIndexErrors": true
10
+ }
11
+ }
package/misairu.js DELETED
@@ -1,255 +0,0 @@
1
- /* misairu
2
- * https://github.com/pixeldesu/misairu
3
- *
4
- *
5
- * Copyright pixeldesu and other contributors
6
- * Licensed under the MIT License
7
- * https://github.com/pixeldesu/misairu/blob/master/LICENSE
8
- */
9
-
10
- class misairu {
11
- constructor (audioSource, timings) {
12
- if (timings === null) console.error('You need to specify a timings object');
13
- this.timings = timings;
14
-
15
- this.audioContext = new AudioContext();
16
- this.audioElement = null;
17
-
18
- this.gainNode = this.audioContext.createGain();
19
- this.gainNode.connect(this.audioContext.destination);
20
-
21
- this.audioSource = audioSource;
22
-
23
- this.eventHandler = null;
24
-
25
- this.cache = {};
26
- }
27
-
28
- set audioContext (audioContext) {
29
- this._audioContext = audioContext;
30
- }
31
-
32
- get audioContext () {
33
- return this._audioContext;
34
- }
35
-
36
- set audioSource (audioSource) {
37
- if (typeof audioSource == "string") {
38
- this.fetchAudioSource(audioSource);
39
- } else if (typeof audioSource == "object" && (audioSource.tagName == "AUDIO" || audioSource.tagName == "VIDEO")) {
40
- this.attachAudioElementSource(audioSource);
41
- }
42
- }
43
-
44
- get audioSource () {
45
- return this._audioSource;
46
- }
47
-
48
- set gainNode (gainNode) {
49
- this._gainNode = gainNode;
50
- }
51
-
52
- get gainNode () {
53
- return this._gainNode;
54
- }
55
-
56
- set audioElement (audioElement) {
57
- this._audioElement = audioElement;
58
- }
59
-
60
- get audioElement () {
61
- return this._audioElement;
62
- }
63
-
64
- set startTime (startTime) {
65
- this._startTime = startTime;
66
- }
67
-
68
- get startTime () {
69
- return this._startTime;
70
- }
71
-
72
- set timings (timings) {
73
- this._timings = timings;
74
- }
75
-
76
- get timings () {
77
- return this._timings;
78
- }
79
-
80
- set cache (cache) {
81
- this._cache = cache;
82
- }
83
-
84
- get cache () {
85
- return this._cache;
86
- }
87
-
88
- set eventHandler (eventHandler) {
89
- this._eventHandler = eventHandler;
90
- }
91
-
92
- get eventHandler () {
93
- return this._eventHandler;
94
- }
95
-
96
- set muted (muted) {
97
- this._muted = muted;
98
- }
99
-
100
- get muted () {
101
- return this._muted;
102
- }
103
-
104
- set volume (db) {
105
- this._volume = db;
106
- this.clampGain();
107
-
108
- if (!this.muted) {
109
- this.gainNode.gain.value = this.dbToVolume(this._volume);
110
- }
111
- }
112
-
113
- get volume () {
114
- return this._volume;
115
- }
116
-
117
- set paused (paused) {
118
- this._paused = paused;
119
- }
120
-
121
- get paused () {
122
- return this._paused;
123
- }
124
-
125
- clampGain () {
126
- if (this._volume < -80) {
127
- this._volume = -80;
128
- } else if (this._volume > 5) {
129
- this._volume = 5;
130
- }
131
- }
132
-
133
- dbToVolume (db) {
134
- return Math.pow(10, db / 20);
135
- }
136
-
137
- mute() {
138
- if (!this.muted) {
139
- this.muted = true;
140
- this.gainNode.gain.value = 0;
141
- }
142
- }
143
-
144
- unmute() {
145
- if (this.muted) {
146
- this.muted = false;
147
- this.gainNode.gain.value = this.dbToVolume(this._volume);
148
- }
149
- }
150
-
151
- pause () {
152
- if (!this.paused) {
153
- this.audioContext.suspend();
154
- this.paused = true;
155
- }
156
- }
157
-
158
- unpause () {
159
- if (this.paused) {
160
- this.audioContext.resume();
161
- this.paused = false;
162
- }
163
- }
164
-
165
- setCacheEntry (track, entry) {
166
- this.cache[track] = entry;
167
- }
168
-
169
- getTrackCache (track) {
170
- return this.cache[track];
171
- }
172
-
173
- getAllTracks () {
174
- return Object.keys(this.timings);
175
- }
176
-
177
- getActiveTimingKey (track, currentTime) {
178
- const timingKeys = Object.keys(this.timings[track]);
179
-
180
- var activeTimings = timingKeys.filter(function (timing) {
181
- if (currentTime >= parseFloat(timing)) {
182
- return true;
183
- }
184
- })
185
-
186
- return activeTimings[activeTimings.length - 1];
187
- }
188
-
189
- fetchAudioSource (audioSource) {
190
- let that = this;
191
- let source = this.audioContext.createBufferSource();
192
-
193
- fetch(audioSource).then((response) => {
194
- return response.arrayBuffer()
195
- }).then((arrayBuffer) => {
196
- that.audioContext.decodeAudioData(arrayBuffer)
197
- .then((buffer) => {
198
- source.buffer = buffer;
199
- source.connect(this.gainNode);
200
-
201
- document.dispatchEvent(new Event('misairu.ready'));
202
- this._audioSource = source;
203
- })
204
- })
205
- }
206
-
207
- attachAudioElementSource (audioSource) {
208
- let source = this.audioContext.createMediaElementSource(audioSource);
209
- this.audioElement = audioSource;
210
-
211
- source.connect(this.gainNode);
212
- this._audioSource = source;
213
- }
214
-
215
- start () {
216
- this.startTime = this.audioContext.currentTime;
217
-
218
- if (this.audioElement !== null) {
219
- this.audioElement.play();
220
- } else {
221
- this.audioSource.start();
222
- }
223
-
224
- this.startEventHandling();
225
- }
226
-
227
- startEventHandling () {
228
- if (this.eventHandler == null) {
229
- this.eventHandler = window.requestAnimationFrame(this.handleEvents.bind(this));
230
- }
231
- }
232
-
233
- handleEvents () {
234
- let time = this.audioContext.currentTime - this.startTime;
235
-
236
- this.getAllTracks().forEach(function (track) {
237
- let timingKey = this.getActiveTimingKey(track, time);
238
-
239
- if (timingKey !== null && !(this.getTrackCache(track) == timingKey)) {
240
- this.executeEvent(track, timingKey, time);
241
- this.setCacheEntry(track, timingKey);
242
- }
243
- }.bind(this))
244
-
245
- this.eventHandler = window.requestAnimationFrame(this.handleEvents.bind(this));
246
- }
247
-
248
- executeEvent (track, timingKey, time) {
249
- this.timings[track][timingKey](this, timingKey, track, time);
250
- }
251
- }
252
-
253
- if (typeof module === 'object' && module.exports) {
254
- module.exports = misairu;
255
- }