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/.eslintignore +3 -0
- package/.eslintrc.js +18 -0
- package/.prettierignore +2 -0
- package/.prettierrc.json +8 -0
- package/LICENSE +20 -20
- package/README.md +144 -115
- package/dist/index.d.ts +2 -0
- package/dist/misairu.d.ts +161 -0
- package/dist/misairu.iife.js +2 -0
- package/dist/misairu.iife.js.map +1 -0
- package/dist/misairu.js +2 -0
- package/dist/misairu.js.map +1 -0
- package/dist/misairu.modern.js +2 -0
- package/dist/misairu.modern.js.map +1 -0
- package/dist/misairu.module.js +2 -0
- package/dist/misairu.module.js.map +1 -0
- package/dist/misairu.umd.js +2 -0
- package/dist/misairu.umd.js.map +1 -0
- package/dist/processors/repeat.d.ts +6 -0
- package/dist/types.d.ts +46 -0
- package/dist/utilities/audio.d.ts +11 -0
- package/dist/utilities/source.d.ts +15 -0
- package/package.json +52 -26
- package/src/index.ts +2 -0
- package/src/misairu.ts +308 -0
- package/src/processors/repeat.ts +35 -0
- package/src/types.ts +58 -0
- package/src/utilities/audio.ts +22 -0
- package/src/utilities/source.ts +28 -0
- package/tsconfig.json +11 -0
- package/misairu.js +0 -255
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
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
|
-
}
|