@mulsense/xnew 0.4.8 → 0.5.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/README.md +3 -3
- package/dist/xnew.js +15 -71
- package/dist/xnew.mjs +15 -71
- package/package.json +1 -1
- package/dist/addons/xaudio.d.ts +0 -53
- package/dist/addons/xaudio.js +0 -256
- package/dist/addons/xaudio.mjs +0 -250
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ providing a flexible architecture well-suited for applications with dynamic scen
|
|
|
13
13
|
### Via CDN
|
|
14
14
|
Include the following script in your HTML file:
|
|
15
15
|
```html
|
|
16
|
-
<script src="https://unpkg.com/@mulsense/xnew@0.
|
|
16
|
+
<script src="https://unpkg.com/@mulsense/xnew@0.5.x/dist/xnew.js"></script>
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
### Via CDN (ESM)
|
|
@@ -22,7 +22,7 @@ Use the ES module version with an import map:
|
|
|
22
22
|
<script type="importmap">
|
|
23
23
|
{
|
|
24
24
|
"imports": {
|
|
25
|
-
"@mulsense/xnew": "https://unpkg.com/@mulsense/xnew@0.
|
|
25
|
+
"@mulsense/xnew": "https://unpkg.com/@mulsense/xnew@0.5.x/dist/xnew.mjs"
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
</script>
|
|
@@ -37,7 +37,7 @@ import xnew from '@mulsense/xnew';
|
|
|
37
37
|
### Via npm
|
|
38
38
|
Install `xnew` using npm:
|
|
39
39
|
```bash
|
|
40
|
-
npm install @mulsense/xnew@0.
|
|
40
|
+
npm install @mulsense/xnew@0.5.x
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Then import it in your JavaScript file:
|
package/dist/xnew.js
CHANGED
|
@@ -206,8 +206,6 @@
|
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
|
|
209
|
-
const SYSTEM_EVENTS = ['start', 'update', 'render', 'stop', 'finalize'];
|
|
210
|
-
|
|
211
209
|
class EventManager {
|
|
212
210
|
constructor() {
|
|
213
211
|
this.map = new MapMap();
|
|
@@ -524,6 +522,10 @@
|
|
|
524
522
|
return { position };
|
|
525
523
|
}
|
|
526
524
|
|
|
525
|
+
//----------------------------------------------------------------------------------------------------
|
|
526
|
+
// utils
|
|
527
|
+
//----------------------------------------------------------------------------------------------------
|
|
528
|
+
const SYSTEM_EVENTS = ['start', 'update', 'render', 'stop', 'finalize'];
|
|
527
529
|
//----------------------------------------------------------------------------------------------------
|
|
528
530
|
// unit
|
|
529
531
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -632,11 +634,11 @@
|
|
|
632
634
|
unit._.state = 'finalized';
|
|
633
635
|
}
|
|
634
636
|
}
|
|
635
|
-
static nest(unit,
|
|
637
|
+
static nest(unit, htmlString, textContent) {
|
|
636
638
|
if (unit._.state !== 'invoked') {
|
|
637
639
|
throw new Error('This function can not be called after initialized.');
|
|
638
640
|
}
|
|
639
|
-
const match =
|
|
641
|
+
const match = htmlString.match(/<((\w+)[^>]*?)\/?>/);
|
|
640
642
|
if (match !== null) {
|
|
641
643
|
let element;
|
|
642
644
|
if (unit._.anchor !== null) {
|
|
@@ -649,11 +651,14 @@
|
|
|
649
651
|
element = unit._.currentElement.children[unit._.currentElement.children.length - 1];
|
|
650
652
|
}
|
|
651
653
|
unit._.currentElement = element;
|
|
654
|
+
if (textContent !== undefined) {
|
|
655
|
+
element.textContent = textContent;
|
|
656
|
+
}
|
|
652
657
|
unit._.elements.push(element);
|
|
653
658
|
return element;
|
|
654
659
|
}
|
|
655
660
|
else {
|
|
656
|
-
throw new Error(`Invalid
|
|
661
|
+
throw new Error(`Invalid html string: ${htmlString}`);
|
|
657
662
|
}
|
|
658
663
|
}
|
|
659
664
|
static extend(unit, component, props) {
|
|
@@ -930,12 +935,6 @@
|
|
|
930
935
|
else if (typeof args[0] === 'string' && args[0].match(/<((\w+)[^>]*?)\/?>/)) {
|
|
931
936
|
target = args.shift();
|
|
932
937
|
}
|
|
933
|
-
else if (typeof args[0] === 'string') {
|
|
934
|
-
const query = args.shift();
|
|
935
|
-
target = document.querySelector(query);
|
|
936
|
-
if (target === null)
|
|
937
|
-
throw new Error(`'${query}' can not be found.`);
|
|
938
|
-
}
|
|
939
938
|
else {
|
|
940
939
|
target = null;
|
|
941
940
|
}
|
|
@@ -951,19 +950,19 @@
|
|
|
951
950
|
}, {
|
|
952
951
|
/**
|
|
953
952
|
* Creates a nested HTML/SVG element within the current component
|
|
954
|
-
* @param
|
|
953
|
+
* @param htmlString - HTML or SVG tag name (e.g., '<div>', '<span>', '<svg>')
|
|
955
954
|
* @returns The created HTML/SVG element
|
|
956
955
|
* @throws Error if called after component initialization
|
|
957
956
|
* @example
|
|
958
957
|
* const div = xnew.nest('<div>')
|
|
959
958
|
* div.textContent = 'Hello'
|
|
960
959
|
*/
|
|
961
|
-
nest(
|
|
960
|
+
nest(htmlString, textContent) {
|
|
962
961
|
try {
|
|
963
|
-
return Unit.nest(Unit.currentUnit,
|
|
962
|
+
return Unit.nest(Unit.currentUnit, htmlString, textContent);
|
|
964
963
|
}
|
|
965
964
|
catch (error) {
|
|
966
|
-
console.error('xnew.nest(
|
|
965
|
+
console.error('xnew.nest(htmlString: string): ', error);
|
|
967
966
|
throw error;
|
|
968
967
|
}
|
|
969
968
|
},
|
|
@@ -1376,51 +1375,6 @@
|
|
|
1376
1375
|
});
|
|
1377
1376
|
}
|
|
1378
1377
|
|
|
1379
|
-
function TextStream(unit, { text = '', speed = 50, fade = 300 } = {}) {
|
|
1380
|
-
const chars = [];
|
|
1381
|
-
for (let i = 0; i < text.length; i++) {
|
|
1382
|
-
const unit = xnew$1('<span>');
|
|
1383
|
-
unit.element.textContent = text[i];
|
|
1384
|
-
unit.element.style.opacity = '0';
|
|
1385
|
-
unit.element.style.transition = `opacity ${fade}ms ease-in-out`;
|
|
1386
|
-
chars.push(unit);
|
|
1387
|
-
}
|
|
1388
|
-
let start = 0;
|
|
1389
|
-
unit.on('start', () => {
|
|
1390
|
-
start = new Date().getTime();
|
|
1391
|
-
});
|
|
1392
|
-
let state = 0;
|
|
1393
|
-
unit.on('update', () => {
|
|
1394
|
-
const index = Math.floor((new Date().getTime() - start) / speed);
|
|
1395
|
-
// Display characters up to the current index (fade in)
|
|
1396
|
-
for (let i = 0; i < chars.length; i++) {
|
|
1397
|
-
if (i <= index) {
|
|
1398
|
-
chars[i].element.style.opacity = '1';
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
if (state === 0 && index >= text.length) {
|
|
1402
|
-
action();
|
|
1403
|
-
}
|
|
1404
|
-
});
|
|
1405
|
-
xnew$1.timeout(() => {
|
|
1406
|
-
xnew$1(document.body).on('click wheel', action);
|
|
1407
|
-
unit.on('keydown', action);
|
|
1408
|
-
}, 100);
|
|
1409
|
-
function action() {
|
|
1410
|
-
if (state === 0) {
|
|
1411
|
-
state = 1;
|
|
1412
|
-
for (let i = 0; i < chars.length; i++) {
|
|
1413
|
-
chars[i].element.style.opacity = '1';
|
|
1414
|
-
}
|
|
1415
|
-
xnew$1.emit('-complete');
|
|
1416
|
-
}
|
|
1417
|
-
else if (state === 1) {
|
|
1418
|
-
state = 2;
|
|
1419
|
-
xnew$1.emit('-next');
|
|
1420
|
-
}
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
|
|
1424
1378
|
const context = new window.AudioContext();
|
|
1425
1379
|
const master = context.createGain();
|
|
1426
1380
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -1649,7 +1603,6 @@
|
|
|
1649
1603
|
Screen,
|
|
1650
1604
|
Modal,
|
|
1651
1605
|
Accordion,
|
|
1652
|
-
TextStream,
|
|
1653
1606
|
AnalogStick,
|
|
1654
1607
|
DirectionalPad,
|
|
1655
1608
|
};
|
|
@@ -1680,16 +1633,7 @@
|
|
|
1680
1633
|
master.gain.value = value;
|
|
1681
1634
|
}
|
|
1682
1635
|
};
|
|
1683
|
-
const
|
|
1684
|
-
Object.defineProperty(temp, 'global', {
|
|
1685
|
-
get: function () {
|
|
1686
|
-
return temp.context('xnew.global');
|
|
1687
|
-
},
|
|
1688
|
-
set: function (value) {
|
|
1689
|
-
temp.context('xnew.global', value);
|
|
1690
|
-
}
|
|
1691
|
-
});
|
|
1692
|
-
const xnew = temp;
|
|
1636
|
+
const xnew = Object.assign(xnew$1, { basics, audio });
|
|
1693
1637
|
|
|
1694
1638
|
return xnew;
|
|
1695
1639
|
|
package/dist/xnew.mjs
CHANGED
|
@@ -200,8 +200,6 @@ class Timer {
|
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
const SYSTEM_EVENTS = ['start', 'update', 'render', 'stop', 'finalize'];
|
|
204
|
-
|
|
205
203
|
class EventManager {
|
|
206
204
|
constructor() {
|
|
207
205
|
this.map = new MapMap();
|
|
@@ -518,6 +516,10 @@ function pointer(element, event) {
|
|
|
518
516
|
return { position };
|
|
519
517
|
}
|
|
520
518
|
|
|
519
|
+
//----------------------------------------------------------------------------------------------------
|
|
520
|
+
// utils
|
|
521
|
+
//----------------------------------------------------------------------------------------------------
|
|
522
|
+
const SYSTEM_EVENTS = ['start', 'update', 'render', 'stop', 'finalize'];
|
|
521
523
|
//----------------------------------------------------------------------------------------------------
|
|
522
524
|
// unit
|
|
523
525
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -626,11 +628,11 @@ class Unit {
|
|
|
626
628
|
unit._.state = 'finalized';
|
|
627
629
|
}
|
|
628
630
|
}
|
|
629
|
-
static nest(unit,
|
|
631
|
+
static nest(unit, htmlString, textContent) {
|
|
630
632
|
if (unit._.state !== 'invoked') {
|
|
631
633
|
throw new Error('This function can not be called after initialized.');
|
|
632
634
|
}
|
|
633
|
-
const match =
|
|
635
|
+
const match = htmlString.match(/<((\w+)[^>]*?)\/?>/);
|
|
634
636
|
if (match !== null) {
|
|
635
637
|
let element;
|
|
636
638
|
if (unit._.anchor !== null) {
|
|
@@ -643,11 +645,14 @@ class Unit {
|
|
|
643
645
|
element = unit._.currentElement.children[unit._.currentElement.children.length - 1];
|
|
644
646
|
}
|
|
645
647
|
unit._.currentElement = element;
|
|
648
|
+
if (textContent !== undefined) {
|
|
649
|
+
element.textContent = textContent;
|
|
650
|
+
}
|
|
646
651
|
unit._.elements.push(element);
|
|
647
652
|
return element;
|
|
648
653
|
}
|
|
649
654
|
else {
|
|
650
|
-
throw new Error(`Invalid
|
|
655
|
+
throw new Error(`Invalid html string: ${htmlString}`);
|
|
651
656
|
}
|
|
652
657
|
}
|
|
653
658
|
static extend(unit, component, props) {
|
|
@@ -924,12 +929,6 @@ function parseArguments(...args) {
|
|
|
924
929
|
else if (typeof args[0] === 'string' && args[0].match(/<((\w+)[^>]*?)\/?>/)) {
|
|
925
930
|
target = args.shift();
|
|
926
931
|
}
|
|
927
|
-
else if (typeof args[0] === 'string') {
|
|
928
|
-
const query = args.shift();
|
|
929
|
-
target = document.querySelector(query);
|
|
930
|
-
if (target === null)
|
|
931
|
-
throw new Error(`'${query}' can not be found.`);
|
|
932
|
-
}
|
|
933
932
|
else {
|
|
934
933
|
target = null;
|
|
935
934
|
}
|
|
@@ -945,19 +944,19 @@ const xnew$1 = Object.assign(function (...args) {
|
|
|
945
944
|
}, {
|
|
946
945
|
/**
|
|
947
946
|
* Creates a nested HTML/SVG element within the current component
|
|
948
|
-
* @param
|
|
947
|
+
* @param htmlString - HTML or SVG tag name (e.g., '<div>', '<span>', '<svg>')
|
|
949
948
|
* @returns The created HTML/SVG element
|
|
950
949
|
* @throws Error if called after component initialization
|
|
951
950
|
* @example
|
|
952
951
|
* const div = xnew.nest('<div>')
|
|
953
952
|
* div.textContent = 'Hello'
|
|
954
953
|
*/
|
|
955
|
-
nest(
|
|
954
|
+
nest(htmlString, textContent) {
|
|
956
955
|
try {
|
|
957
|
-
return Unit.nest(Unit.currentUnit,
|
|
956
|
+
return Unit.nest(Unit.currentUnit, htmlString, textContent);
|
|
958
957
|
}
|
|
959
958
|
catch (error) {
|
|
960
|
-
console.error('xnew.nest(
|
|
959
|
+
console.error('xnew.nest(htmlString: string): ', error);
|
|
961
960
|
throw error;
|
|
962
961
|
}
|
|
963
962
|
},
|
|
@@ -1370,51 +1369,6 @@ function DirectionalPad(unit, { diagonal = true, stroke = 'currentColor', stroke
|
|
|
1370
1369
|
});
|
|
1371
1370
|
}
|
|
1372
1371
|
|
|
1373
|
-
function TextStream(unit, { text = '', speed = 50, fade = 300 } = {}) {
|
|
1374
|
-
const chars = [];
|
|
1375
|
-
for (let i = 0; i < text.length; i++) {
|
|
1376
|
-
const unit = xnew$1('<span>');
|
|
1377
|
-
unit.element.textContent = text[i];
|
|
1378
|
-
unit.element.style.opacity = '0';
|
|
1379
|
-
unit.element.style.transition = `opacity ${fade}ms ease-in-out`;
|
|
1380
|
-
chars.push(unit);
|
|
1381
|
-
}
|
|
1382
|
-
let start = 0;
|
|
1383
|
-
unit.on('start', () => {
|
|
1384
|
-
start = new Date().getTime();
|
|
1385
|
-
});
|
|
1386
|
-
let state = 0;
|
|
1387
|
-
unit.on('update', () => {
|
|
1388
|
-
const index = Math.floor((new Date().getTime() - start) / speed);
|
|
1389
|
-
// Display characters up to the current index (fade in)
|
|
1390
|
-
for (let i = 0; i < chars.length; i++) {
|
|
1391
|
-
if (i <= index) {
|
|
1392
|
-
chars[i].element.style.opacity = '1';
|
|
1393
|
-
}
|
|
1394
|
-
}
|
|
1395
|
-
if (state === 0 && index >= text.length) {
|
|
1396
|
-
action();
|
|
1397
|
-
}
|
|
1398
|
-
});
|
|
1399
|
-
xnew$1.timeout(() => {
|
|
1400
|
-
xnew$1(document.body).on('click wheel', action);
|
|
1401
|
-
unit.on('keydown', action);
|
|
1402
|
-
}, 100);
|
|
1403
|
-
function action() {
|
|
1404
|
-
if (state === 0) {
|
|
1405
|
-
state = 1;
|
|
1406
|
-
for (let i = 0; i < chars.length; i++) {
|
|
1407
|
-
chars[i].element.style.opacity = '1';
|
|
1408
|
-
}
|
|
1409
|
-
xnew$1.emit('-complete');
|
|
1410
|
-
}
|
|
1411
|
-
else if (state === 1) {
|
|
1412
|
-
state = 2;
|
|
1413
|
-
xnew$1.emit('-next');
|
|
1414
|
-
}
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
1372
|
const context = new window.AudioContext();
|
|
1419
1373
|
const master = context.createGain();
|
|
1420
1374
|
//----------------------------------------------------------------------------------------------------
|
|
@@ -1643,7 +1597,6 @@ const basics = {
|
|
|
1643
1597
|
Screen,
|
|
1644
1598
|
Modal,
|
|
1645
1599
|
Accordion,
|
|
1646
|
-
TextStream,
|
|
1647
1600
|
AnalogStick,
|
|
1648
1601
|
DirectionalPad,
|
|
1649
1602
|
};
|
|
@@ -1674,15 +1627,6 @@ const audio = {
|
|
|
1674
1627
|
master.gain.value = value;
|
|
1675
1628
|
}
|
|
1676
1629
|
};
|
|
1677
|
-
const
|
|
1678
|
-
Object.defineProperty(temp, 'global', {
|
|
1679
|
-
get: function () {
|
|
1680
|
-
return temp.context('xnew.global');
|
|
1681
|
-
},
|
|
1682
|
-
set: function (value) {
|
|
1683
|
-
temp.context('xnew.global', value);
|
|
1684
|
-
}
|
|
1685
|
-
});
|
|
1686
|
-
const xnew = temp;
|
|
1630
|
+
const xnew = Object.assign(xnew$1, { basics, audio });
|
|
1687
1631
|
|
|
1688
1632
|
export { xnew as default };
|
package/package.json
CHANGED
package/dist/addons/xaudio.d.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
declare const _default: {
|
|
2
|
-
load(path: string): {
|
|
3
|
-
promise: Promise<any>;
|
|
4
|
-
component: Function | null;
|
|
5
|
-
then(callback: Function): /*elided*/ any;
|
|
6
|
-
catch(callback: Function): /*elided*/ any;
|
|
7
|
-
finally(callback: Function): /*elided*/ any;
|
|
8
|
-
};
|
|
9
|
-
synthesizer(props: SynthesizerOptions): Synthesizer;
|
|
10
|
-
volume: number;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
type SynthesizerOptions = {
|
|
14
|
-
oscillator: OscillatorOptions;
|
|
15
|
-
amp: AmpOptions;
|
|
16
|
-
filter?: FilterOptions;
|
|
17
|
-
reverb?: ReverbOptions;
|
|
18
|
-
bpm?: number;
|
|
19
|
-
};
|
|
20
|
-
type OscillatorOptions = {
|
|
21
|
-
type: OscillatorType;
|
|
22
|
-
envelope?: Envelope;
|
|
23
|
-
LFO?: LFO;
|
|
24
|
-
};
|
|
25
|
-
type FilterOptions = {
|
|
26
|
-
type: BiquadFilterType;
|
|
27
|
-
cutoff: number;
|
|
28
|
-
};
|
|
29
|
-
type AmpOptions = {
|
|
30
|
-
envelope: Envelope;
|
|
31
|
-
};
|
|
32
|
-
type ReverbOptions = {
|
|
33
|
-
time: number;
|
|
34
|
-
mix: number;
|
|
35
|
-
};
|
|
36
|
-
type Envelope = {
|
|
37
|
-
amount: number;
|
|
38
|
-
ADSR: [number, number, number, number];
|
|
39
|
-
};
|
|
40
|
-
type LFO = {
|
|
41
|
-
amount: number;
|
|
42
|
-
type: OscillatorType;
|
|
43
|
-
rate: number;
|
|
44
|
-
};
|
|
45
|
-
declare class Synthesizer {
|
|
46
|
-
props: SynthesizerOptions;
|
|
47
|
-
constructor(props: SynthesizerOptions);
|
|
48
|
-
press(frequency: number | string, duration?: number | string, wait?: number): {
|
|
49
|
-
release: () => void;
|
|
50
|
-
} | undefined;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export { _default as default };
|
package/dist/addons/xaudio.js
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@mulsense/xnew')) :
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['@mulsense/xnew'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.xaudio = factory(global.xnew));
|
|
5
|
-
})(this, (function (xnew) { 'use strict';
|
|
6
|
-
|
|
7
|
-
var xaudio = {
|
|
8
|
-
load(path) {
|
|
9
|
-
const music = new AudioFile(path);
|
|
10
|
-
const object = {
|
|
11
|
-
play(options) {
|
|
12
|
-
const unit = xnew();
|
|
13
|
-
if (music.played === null) {
|
|
14
|
-
music.play(options);
|
|
15
|
-
unit.on('finalize', () => music.pause({ fade: options.fade }));
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
pause(options) {
|
|
19
|
-
music.pause(options);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
return xnew.promise(music.promise).then(() => object);
|
|
23
|
-
},
|
|
24
|
-
synthesizer(props) {
|
|
25
|
-
return new Synthesizer(props);
|
|
26
|
-
},
|
|
27
|
-
get volume() {
|
|
28
|
-
return master.gain.value;
|
|
29
|
-
},
|
|
30
|
-
set volume(value) {
|
|
31
|
-
master.gain.value = value;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
const context = window.AudioContext ? new window.AudioContext() : (null);
|
|
35
|
-
const master = context ? context.createGain() : (null);
|
|
36
|
-
if (context) {
|
|
37
|
-
master.gain.value = 0.1;
|
|
38
|
-
master.connect(context.destination);
|
|
39
|
-
}
|
|
40
|
-
class AudioFile {
|
|
41
|
-
constructor(path) {
|
|
42
|
-
this.promise = fetch(path)
|
|
43
|
-
.then((response) => response.arrayBuffer())
|
|
44
|
-
.then((response) => context.decodeAudioData(response))
|
|
45
|
-
.then((response) => { this.buffer = response; })
|
|
46
|
-
.catch(() => {
|
|
47
|
-
console.warn(`"${path}" could not be loaded.`);
|
|
48
|
-
});
|
|
49
|
-
this.amp = context.createGain();
|
|
50
|
-
this.amp.gain.value = 1.0;
|
|
51
|
-
this.amp.connect(master);
|
|
52
|
-
this.fade = context.createGain();
|
|
53
|
-
this.fade.gain.value = 1.0;
|
|
54
|
-
this.fade.connect(this.amp);
|
|
55
|
-
this.source = null;
|
|
56
|
-
this.played = null;
|
|
57
|
-
}
|
|
58
|
-
set volume(value) {
|
|
59
|
-
this.amp.gain.value = value;
|
|
60
|
-
}
|
|
61
|
-
get volume() {
|
|
62
|
-
return this.amp.gain.value;
|
|
63
|
-
}
|
|
64
|
-
play({ offset = 0, fade = 0, loop = false } = {}) {
|
|
65
|
-
if (this.buffer !== undefined && this.played === null) {
|
|
66
|
-
this.source = context.createBufferSource();
|
|
67
|
-
this.source.buffer = this.buffer;
|
|
68
|
-
this.source.loop = loop;
|
|
69
|
-
this.source.connect(this.fade);
|
|
70
|
-
this.played = context.currentTime;
|
|
71
|
-
this.source.playbackRate.value = 1;
|
|
72
|
-
this.source.start(context.currentTime, offset / 1000);
|
|
73
|
-
// Apply fade-in effect if fade duration is specified
|
|
74
|
-
if (fade > 0) {
|
|
75
|
-
this.fade.gain.setValueAtTime(0, context.currentTime);
|
|
76
|
-
this.fade.gain.linearRampToValueAtTime(1.0, context.currentTime + fade / 1000);
|
|
77
|
-
}
|
|
78
|
-
this.source.onended = () => {
|
|
79
|
-
var _a;
|
|
80
|
-
this.played = null;
|
|
81
|
-
(_a = this.source) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
82
|
-
this.source = null;
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
pause({ fade = 0 } = {}) {
|
|
87
|
-
var _a, _b;
|
|
88
|
-
if (this.buffer !== undefined && this.played !== null) {
|
|
89
|
-
const elapsed = (context.currentTime - this.played) % this.buffer.duration * 1000;
|
|
90
|
-
// Apply fade-out effect if fade duration is specified
|
|
91
|
-
if (fade > 0) {
|
|
92
|
-
this.fade.gain.setValueAtTime(1.0, context.currentTime);
|
|
93
|
-
this.fade.gain.linearRampToValueAtTime(0, context.currentTime + fade / 1000);
|
|
94
|
-
(_a = this.source) === null || _a === void 0 ? void 0 : _a.stop(context.currentTime + fade / 1000);
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
(_b = this.source) === null || _b === void 0 ? void 0 : _b.stop(context.currentTime);
|
|
98
|
-
}
|
|
99
|
-
this.played = null;
|
|
100
|
-
return elapsed;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
clear() {
|
|
104
|
-
var _a;
|
|
105
|
-
this.amp.disconnect();
|
|
106
|
-
this.fade.disconnect();
|
|
107
|
-
(_a = this.source) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
const keymap = {
|
|
111
|
-
'A0': 27.500, 'A#0': 29.135, 'B0': 30.868,
|
|
112
|
-
'C1': 32.703, 'C#1': 34.648, 'D1': 36.708, 'D#1': 38.891, 'E1': 41.203, 'F1': 43.654, 'F#1': 46.249, 'G1': 48.999, 'G#1': 51.913, 'A1': 55.000, 'A#1': 58.270, 'B1': 61.735,
|
|
113
|
-
'C2': 65.406, 'C#2': 69.296, 'D2': 73.416, 'D#2': 77.782, 'E2': 82.407, 'F2': 87.307, 'F#2': 92.499, 'G2': 97.999, 'G#2': 103.826, 'A2': 110.000, 'A#2': 116.541, 'B2': 123.471,
|
|
114
|
-
'C3': 130.813, 'C#3': 138.591, 'D3': 146.832, 'D#3': 155.563, 'E3': 164.814, 'F3': 174.614, 'F#3': 184.997, 'G3': 195.998, 'G#3': 207.652, 'A3': 220.000, 'A#3': 233.082, 'B3': 246.942,
|
|
115
|
-
'C4': 261.626, 'C#4': 277.183, 'D4': 293.665, 'D#4': 311.127, 'E4': 329.628, 'F4': 349.228, 'F#4': 369.994, 'G4': 391.995, 'G#4': 415.305, 'A4': 440.000, 'A#4': 466.164, 'B4': 493.883,
|
|
116
|
-
'C5': 523.251, 'C#5': 554.365, 'D5': 587.330, 'D#5': 622.254, 'E5': 659.255, 'F5': 698.456, 'F#5': 739.989, 'G5': 783.991, 'G#5': 830.609, 'A5': 880.000, 'A#5': 932.328, 'B5': 987.767,
|
|
117
|
-
'C6': 1046.502, 'C#6': 1108.731, 'D6': 1174.659, 'D#6': 1244.508, 'E6': 1318.510, 'F6': 1396.913, 'F#6': 1479.978, 'G6': 1567.982, 'G#6': 1661.219, 'A6': 1760.000, 'A#6': 1864.655, 'B6': 1975.533,
|
|
118
|
-
'C7': 2093.005, 'C#7': 2217.461, 'D7': 2349.318, 'D#7': 2489.016, 'E7': 2637.020, 'F7': 2793.826, 'F#7': 2959.955, 'G7': 3135.963, 'G#7': 3322.438, 'A7': 3520.000, 'A#7': 3729.310, 'B7': 3951.066,
|
|
119
|
-
'C8': 4186.009,
|
|
120
|
-
};
|
|
121
|
-
const notemap = {
|
|
122
|
-
'1m': 4.000, '2n': 2.000, '4n': 1.000, '8n': 0.500, '16n': 0.250, '32n': 0.125,
|
|
123
|
-
};
|
|
124
|
-
class Synthesizer {
|
|
125
|
-
constructor(props) { this.props = props; }
|
|
126
|
-
press(frequency, duration, wait) {
|
|
127
|
-
var _a;
|
|
128
|
-
const props = this.props;
|
|
129
|
-
const fv = typeof frequency === 'string' ? keymap[frequency] : frequency;
|
|
130
|
-
const dv = typeof duration === 'string' ? (notemap[duration] * 60 / ((_a = props.bpm) !== null && _a !== void 0 ? _a : 120)) : (typeof duration === 'number' ? (duration / 1000) : 0);
|
|
131
|
-
const start = context.currentTime + (wait !== null && wait !== void 0 ? wait : 0) / 1000;
|
|
132
|
-
const nodes = {};
|
|
133
|
-
nodes.oscillator = context.createOscillator();
|
|
134
|
-
nodes.oscillator.type = props.oscillator.type;
|
|
135
|
-
nodes.oscillator.frequency.value = fv;
|
|
136
|
-
if (props.oscillator.LFO) {
|
|
137
|
-
nodes.oscillatorLFO = context.createOscillator();
|
|
138
|
-
nodes.oscillatorLFODepth = context.createGain();
|
|
139
|
-
nodes.oscillatorLFODepth.gain.value = fv * (Math.pow(2.0, props.oscillator.LFO.amount / 12.0) - 1.0);
|
|
140
|
-
nodes.oscillatorLFO.type = props.oscillator.LFO.type;
|
|
141
|
-
nodes.oscillatorLFO.frequency.value = props.oscillator.LFO.rate;
|
|
142
|
-
nodes.oscillatorLFO.start(start);
|
|
143
|
-
nodes.oscillatorLFO.connect(nodes.oscillatorLFODepth);
|
|
144
|
-
nodes.oscillatorLFODepth.connect(nodes.oscillator.frequency);
|
|
145
|
-
}
|
|
146
|
-
nodes.amp = context.createGain();
|
|
147
|
-
nodes.amp.gain.value = 0.0;
|
|
148
|
-
nodes.target = context.createGain();
|
|
149
|
-
nodes.target.gain.value = 1.0;
|
|
150
|
-
nodes.amp.connect(nodes.target);
|
|
151
|
-
nodes.target.connect(master);
|
|
152
|
-
if (props.filter) {
|
|
153
|
-
nodes.filter = context.createBiquadFilter();
|
|
154
|
-
nodes.filter.type = props.filter.type;
|
|
155
|
-
nodes.filter.frequency.value = props.filter.cutoff;
|
|
156
|
-
nodes.oscillator.connect(nodes.filter);
|
|
157
|
-
nodes.filter.connect(nodes.amp);
|
|
158
|
-
}
|
|
159
|
-
else {
|
|
160
|
-
nodes.oscillator.connect(nodes.amp);
|
|
161
|
-
}
|
|
162
|
-
if (props.reverb) {
|
|
163
|
-
nodes.convolver = context.createConvolver();
|
|
164
|
-
nodes.convolver.buffer = impulseResponse({ time: props.reverb.time });
|
|
165
|
-
nodes.convolverDepth = context.createGain();
|
|
166
|
-
nodes.convolverDepth.gain.value = 1.0;
|
|
167
|
-
nodes.convolverDepth.gain.value *= props.reverb.mix;
|
|
168
|
-
nodes.target.gain.value *= (1.0 - props.reverb.mix);
|
|
169
|
-
nodes.amp.connect(nodes.convolver);
|
|
170
|
-
nodes.convolver.connect(nodes.convolverDepth);
|
|
171
|
-
nodes.convolverDepth.connect(master);
|
|
172
|
-
}
|
|
173
|
-
if (props.oscillator.envelope) {
|
|
174
|
-
const amount = fv * (Math.pow(2.0, props.oscillator.envelope.amount / 12.0) - 1.0);
|
|
175
|
-
startEnvelope(nodes.oscillator.frequency, fv, amount, props.oscillator.envelope.ADSR);
|
|
176
|
-
}
|
|
177
|
-
if (props.amp.envelope) {
|
|
178
|
-
startEnvelope(nodes.amp.gain, 0.0, props.amp.envelope.amount, props.amp.envelope.ADSR);
|
|
179
|
-
}
|
|
180
|
-
nodes.oscillator.start(start);
|
|
181
|
-
if (dv > 0) {
|
|
182
|
-
release();
|
|
183
|
-
}
|
|
184
|
-
else {
|
|
185
|
-
return { release };
|
|
186
|
-
}
|
|
187
|
-
function release() {
|
|
188
|
-
let stop = null;
|
|
189
|
-
const end = dv > 0 ? dv : (context.currentTime - start);
|
|
190
|
-
if (props.amp.envelope) {
|
|
191
|
-
const ADSR = props.amp.envelope.ADSR;
|
|
192
|
-
const adsr = [ADSR[0] / 1000, ADSR[1] / 1000, ADSR[2], ADSR[3] / 1000];
|
|
193
|
-
const rate = adsr[0] === 0.0 ? 1.0 : Math.min(end / (adsr[0] + 0.001), 1.0);
|
|
194
|
-
stop = start + Math.max((adsr[0] + adsr[1]) * rate, end) + adsr[3];
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
stop = start + end;
|
|
198
|
-
}
|
|
199
|
-
if (nodes.oscillatorLFO) {
|
|
200
|
-
nodes.oscillatorLFO.stop(stop);
|
|
201
|
-
}
|
|
202
|
-
if (props.oscillator.envelope) {
|
|
203
|
-
const amount = fv * (Math.pow(2.0, props.oscillator.envelope.amount / 12.0) - 1.0);
|
|
204
|
-
stopEnvelope(nodes.oscillator.frequency, fv, amount, props.oscillator.envelope.ADSR);
|
|
205
|
-
}
|
|
206
|
-
if (props.amp.envelope) {
|
|
207
|
-
stopEnvelope(nodes.amp.gain, 0.0, props.amp.envelope.amount, props.amp.envelope.ADSR);
|
|
208
|
-
}
|
|
209
|
-
nodes.oscillator.stop(stop);
|
|
210
|
-
setTimeout(() => {
|
|
211
|
-
var _a, _b, _c, _d, _e;
|
|
212
|
-
nodes.oscillator.disconnect();
|
|
213
|
-
nodes.amp.disconnect();
|
|
214
|
-
nodes.target.disconnect();
|
|
215
|
-
(_a = nodes.oscillatorLFO) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
216
|
-
(_b = nodes.oscillatorLFODepth) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
217
|
-
(_c = nodes.filter) === null || _c === void 0 ? void 0 : _c.disconnect();
|
|
218
|
-
(_d = nodes.convolver) === null || _d === void 0 ? void 0 : _d.disconnect();
|
|
219
|
-
(_e = nodes.convolverDepth) === null || _e === void 0 ? void 0 : _e.disconnect();
|
|
220
|
-
}, 2000);
|
|
221
|
-
}
|
|
222
|
-
function stopEnvelope(param, base, amount, ADSR) {
|
|
223
|
-
const end = dv > 0 ? dv : (context.currentTime - start);
|
|
224
|
-
const rate = ADSR[0] === 0.0 ? 1.0 : Math.min(end / (ADSR[0] / 1000), 1.0);
|
|
225
|
-
if (rate < 1.0) {
|
|
226
|
-
param.cancelScheduledValues(start);
|
|
227
|
-
param.setValueAtTime(base, start);
|
|
228
|
-
param.linearRampToValueAtTime(base + amount * rate, start + ADSR[0] / 1000 * rate);
|
|
229
|
-
param.linearRampToValueAtTime(base + amount * rate * ADSR[2], start + (ADSR[0] + ADSR[1]) / 1000 * rate);
|
|
230
|
-
}
|
|
231
|
-
param.linearRampToValueAtTime(base + amount * rate * ADSR[2], start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate, dv));
|
|
232
|
-
param.linearRampToValueAtTime(base, start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate, end) + ADSR[3] / 1000);
|
|
233
|
-
}
|
|
234
|
-
function startEnvelope(param, base, amount, ADSR) {
|
|
235
|
-
param.value = base;
|
|
236
|
-
param.setValueAtTime(base, start);
|
|
237
|
-
param.linearRampToValueAtTime(base + amount, start + ADSR[0] / 1000);
|
|
238
|
-
param.linearRampToValueAtTime(base + amount * ADSR[2], start + (ADSR[0] + ADSR[1]) / 1000);
|
|
239
|
-
}
|
|
240
|
-
function impulseResponse({ time, decay = 2.0 }) {
|
|
241
|
-
const length = context.sampleRate * time / 1000;
|
|
242
|
-
const impulse = context.createBuffer(2, length, context.sampleRate);
|
|
243
|
-
const ch0 = impulse.getChannelData(0);
|
|
244
|
-
const ch1 = impulse.getChannelData(1);
|
|
245
|
-
for (let i = 0; i < length; i++) {
|
|
246
|
-
ch0[i] = (2 * Math.random() - 1) * Math.pow(1 - i / length, decay);
|
|
247
|
-
ch1[i] = (2 * Math.random() - 1) * Math.pow(1 - i / length, decay);
|
|
248
|
-
}
|
|
249
|
-
return impulse;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
return xaudio;
|
|
255
|
-
|
|
256
|
-
}));
|
package/dist/addons/xaudio.mjs
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
import xnew from '@mulsense/xnew';
|
|
2
|
-
|
|
3
|
-
var xaudio = {
|
|
4
|
-
load(path) {
|
|
5
|
-
const music = new AudioFile(path);
|
|
6
|
-
const object = {
|
|
7
|
-
play(options) {
|
|
8
|
-
const unit = xnew();
|
|
9
|
-
if (music.played === null) {
|
|
10
|
-
music.play(options);
|
|
11
|
-
unit.on('finalize', () => music.pause({ fade: options.fade }));
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
pause(options) {
|
|
15
|
-
music.pause(options);
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
return xnew.promise(music.promise).then(() => object);
|
|
19
|
-
},
|
|
20
|
-
synthesizer(props) {
|
|
21
|
-
return new Synthesizer(props);
|
|
22
|
-
},
|
|
23
|
-
get volume() {
|
|
24
|
-
return master.gain.value;
|
|
25
|
-
},
|
|
26
|
-
set volume(value) {
|
|
27
|
-
master.gain.value = value;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
const context = window.AudioContext ? new window.AudioContext() : (null);
|
|
31
|
-
const master = context ? context.createGain() : (null);
|
|
32
|
-
if (context) {
|
|
33
|
-
master.gain.value = 0.1;
|
|
34
|
-
master.connect(context.destination);
|
|
35
|
-
}
|
|
36
|
-
class AudioFile {
|
|
37
|
-
constructor(path) {
|
|
38
|
-
this.promise = fetch(path)
|
|
39
|
-
.then((response) => response.arrayBuffer())
|
|
40
|
-
.then((response) => context.decodeAudioData(response))
|
|
41
|
-
.then((response) => { this.buffer = response; })
|
|
42
|
-
.catch(() => {
|
|
43
|
-
console.warn(`"${path}" could not be loaded.`);
|
|
44
|
-
});
|
|
45
|
-
this.amp = context.createGain();
|
|
46
|
-
this.amp.gain.value = 1.0;
|
|
47
|
-
this.amp.connect(master);
|
|
48
|
-
this.fade = context.createGain();
|
|
49
|
-
this.fade.gain.value = 1.0;
|
|
50
|
-
this.fade.connect(this.amp);
|
|
51
|
-
this.source = null;
|
|
52
|
-
this.played = null;
|
|
53
|
-
}
|
|
54
|
-
set volume(value) {
|
|
55
|
-
this.amp.gain.value = value;
|
|
56
|
-
}
|
|
57
|
-
get volume() {
|
|
58
|
-
return this.amp.gain.value;
|
|
59
|
-
}
|
|
60
|
-
play({ offset = 0, fade = 0, loop = false } = {}) {
|
|
61
|
-
if (this.buffer !== undefined && this.played === null) {
|
|
62
|
-
this.source = context.createBufferSource();
|
|
63
|
-
this.source.buffer = this.buffer;
|
|
64
|
-
this.source.loop = loop;
|
|
65
|
-
this.source.connect(this.fade);
|
|
66
|
-
this.played = context.currentTime;
|
|
67
|
-
this.source.playbackRate.value = 1;
|
|
68
|
-
this.source.start(context.currentTime, offset / 1000);
|
|
69
|
-
// Apply fade-in effect if fade duration is specified
|
|
70
|
-
if (fade > 0) {
|
|
71
|
-
this.fade.gain.setValueAtTime(0, context.currentTime);
|
|
72
|
-
this.fade.gain.linearRampToValueAtTime(1.0, context.currentTime + fade / 1000);
|
|
73
|
-
}
|
|
74
|
-
this.source.onended = () => {
|
|
75
|
-
var _a;
|
|
76
|
-
this.played = null;
|
|
77
|
-
(_a = this.source) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
78
|
-
this.source = null;
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
pause({ fade = 0 } = {}) {
|
|
83
|
-
var _a, _b;
|
|
84
|
-
if (this.buffer !== undefined && this.played !== null) {
|
|
85
|
-
const elapsed = (context.currentTime - this.played) % this.buffer.duration * 1000;
|
|
86
|
-
// Apply fade-out effect if fade duration is specified
|
|
87
|
-
if (fade > 0) {
|
|
88
|
-
this.fade.gain.setValueAtTime(1.0, context.currentTime);
|
|
89
|
-
this.fade.gain.linearRampToValueAtTime(0, context.currentTime + fade / 1000);
|
|
90
|
-
(_a = this.source) === null || _a === void 0 ? void 0 : _a.stop(context.currentTime + fade / 1000);
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
(_b = this.source) === null || _b === void 0 ? void 0 : _b.stop(context.currentTime);
|
|
94
|
-
}
|
|
95
|
-
this.played = null;
|
|
96
|
-
return elapsed;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
clear() {
|
|
100
|
-
var _a;
|
|
101
|
-
this.amp.disconnect();
|
|
102
|
-
this.fade.disconnect();
|
|
103
|
-
(_a = this.source) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
const keymap = {
|
|
107
|
-
'A0': 27.500, 'A#0': 29.135, 'B0': 30.868,
|
|
108
|
-
'C1': 32.703, 'C#1': 34.648, 'D1': 36.708, 'D#1': 38.891, 'E1': 41.203, 'F1': 43.654, 'F#1': 46.249, 'G1': 48.999, 'G#1': 51.913, 'A1': 55.000, 'A#1': 58.270, 'B1': 61.735,
|
|
109
|
-
'C2': 65.406, 'C#2': 69.296, 'D2': 73.416, 'D#2': 77.782, 'E2': 82.407, 'F2': 87.307, 'F#2': 92.499, 'G2': 97.999, 'G#2': 103.826, 'A2': 110.000, 'A#2': 116.541, 'B2': 123.471,
|
|
110
|
-
'C3': 130.813, 'C#3': 138.591, 'D3': 146.832, 'D#3': 155.563, 'E3': 164.814, 'F3': 174.614, 'F#3': 184.997, 'G3': 195.998, 'G#3': 207.652, 'A3': 220.000, 'A#3': 233.082, 'B3': 246.942,
|
|
111
|
-
'C4': 261.626, 'C#4': 277.183, 'D4': 293.665, 'D#4': 311.127, 'E4': 329.628, 'F4': 349.228, 'F#4': 369.994, 'G4': 391.995, 'G#4': 415.305, 'A4': 440.000, 'A#4': 466.164, 'B4': 493.883,
|
|
112
|
-
'C5': 523.251, 'C#5': 554.365, 'D5': 587.330, 'D#5': 622.254, 'E5': 659.255, 'F5': 698.456, 'F#5': 739.989, 'G5': 783.991, 'G#5': 830.609, 'A5': 880.000, 'A#5': 932.328, 'B5': 987.767,
|
|
113
|
-
'C6': 1046.502, 'C#6': 1108.731, 'D6': 1174.659, 'D#6': 1244.508, 'E6': 1318.510, 'F6': 1396.913, 'F#6': 1479.978, 'G6': 1567.982, 'G#6': 1661.219, 'A6': 1760.000, 'A#6': 1864.655, 'B6': 1975.533,
|
|
114
|
-
'C7': 2093.005, 'C#7': 2217.461, 'D7': 2349.318, 'D#7': 2489.016, 'E7': 2637.020, 'F7': 2793.826, 'F#7': 2959.955, 'G7': 3135.963, 'G#7': 3322.438, 'A7': 3520.000, 'A#7': 3729.310, 'B7': 3951.066,
|
|
115
|
-
'C8': 4186.009,
|
|
116
|
-
};
|
|
117
|
-
const notemap = {
|
|
118
|
-
'1m': 4.000, '2n': 2.000, '4n': 1.000, '8n': 0.500, '16n': 0.250, '32n': 0.125,
|
|
119
|
-
};
|
|
120
|
-
class Synthesizer {
|
|
121
|
-
constructor(props) { this.props = props; }
|
|
122
|
-
press(frequency, duration, wait) {
|
|
123
|
-
var _a;
|
|
124
|
-
const props = this.props;
|
|
125
|
-
const fv = typeof frequency === 'string' ? keymap[frequency] : frequency;
|
|
126
|
-
const dv = typeof duration === 'string' ? (notemap[duration] * 60 / ((_a = props.bpm) !== null && _a !== void 0 ? _a : 120)) : (typeof duration === 'number' ? (duration / 1000) : 0);
|
|
127
|
-
const start = context.currentTime + (wait !== null && wait !== void 0 ? wait : 0) / 1000;
|
|
128
|
-
const nodes = {};
|
|
129
|
-
nodes.oscillator = context.createOscillator();
|
|
130
|
-
nodes.oscillator.type = props.oscillator.type;
|
|
131
|
-
nodes.oscillator.frequency.value = fv;
|
|
132
|
-
if (props.oscillator.LFO) {
|
|
133
|
-
nodes.oscillatorLFO = context.createOscillator();
|
|
134
|
-
nodes.oscillatorLFODepth = context.createGain();
|
|
135
|
-
nodes.oscillatorLFODepth.gain.value = fv * (Math.pow(2.0, props.oscillator.LFO.amount / 12.0) - 1.0);
|
|
136
|
-
nodes.oscillatorLFO.type = props.oscillator.LFO.type;
|
|
137
|
-
nodes.oscillatorLFO.frequency.value = props.oscillator.LFO.rate;
|
|
138
|
-
nodes.oscillatorLFO.start(start);
|
|
139
|
-
nodes.oscillatorLFO.connect(nodes.oscillatorLFODepth);
|
|
140
|
-
nodes.oscillatorLFODepth.connect(nodes.oscillator.frequency);
|
|
141
|
-
}
|
|
142
|
-
nodes.amp = context.createGain();
|
|
143
|
-
nodes.amp.gain.value = 0.0;
|
|
144
|
-
nodes.target = context.createGain();
|
|
145
|
-
nodes.target.gain.value = 1.0;
|
|
146
|
-
nodes.amp.connect(nodes.target);
|
|
147
|
-
nodes.target.connect(master);
|
|
148
|
-
if (props.filter) {
|
|
149
|
-
nodes.filter = context.createBiquadFilter();
|
|
150
|
-
nodes.filter.type = props.filter.type;
|
|
151
|
-
nodes.filter.frequency.value = props.filter.cutoff;
|
|
152
|
-
nodes.oscillator.connect(nodes.filter);
|
|
153
|
-
nodes.filter.connect(nodes.amp);
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
nodes.oscillator.connect(nodes.amp);
|
|
157
|
-
}
|
|
158
|
-
if (props.reverb) {
|
|
159
|
-
nodes.convolver = context.createConvolver();
|
|
160
|
-
nodes.convolver.buffer = impulseResponse({ time: props.reverb.time });
|
|
161
|
-
nodes.convolverDepth = context.createGain();
|
|
162
|
-
nodes.convolverDepth.gain.value = 1.0;
|
|
163
|
-
nodes.convolverDepth.gain.value *= props.reverb.mix;
|
|
164
|
-
nodes.target.gain.value *= (1.0 - props.reverb.mix);
|
|
165
|
-
nodes.amp.connect(nodes.convolver);
|
|
166
|
-
nodes.convolver.connect(nodes.convolverDepth);
|
|
167
|
-
nodes.convolverDepth.connect(master);
|
|
168
|
-
}
|
|
169
|
-
if (props.oscillator.envelope) {
|
|
170
|
-
const amount = fv * (Math.pow(2.0, props.oscillator.envelope.amount / 12.0) - 1.0);
|
|
171
|
-
startEnvelope(nodes.oscillator.frequency, fv, amount, props.oscillator.envelope.ADSR);
|
|
172
|
-
}
|
|
173
|
-
if (props.amp.envelope) {
|
|
174
|
-
startEnvelope(nodes.amp.gain, 0.0, props.amp.envelope.amount, props.amp.envelope.ADSR);
|
|
175
|
-
}
|
|
176
|
-
nodes.oscillator.start(start);
|
|
177
|
-
if (dv > 0) {
|
|
178
|
-
release();
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
return { release };
|
|
182
|
-
}
|
|
183
|
-
function release() {
|
|
184
|
-
let stop = null;
|
|
185
|
-
const end = dv > 0 ? dv : (context.currentTime - start);
|
|
186
|
-
if (props.amp.envelope) {
|
|
187
|
-
const ADSR = props.amp.envelope.ADSR;
|
|
188
|
-
const adsr = [ADSR[0] / 1000, ADSR[1] / 1000, ADSR[2], ADSR[3] / 1000];
|
|
189
|
-
const rate = adsr[0] === 0.0 ? 1.0 : Math.min(end / (adsr[0] + 0.001), 1.0);
|
|
190
|
-
stop = start + Math.max((adsr[0] + adsr[1]) * rate, end) + adsr[3];
|
|
191
|
-
}
|
|
192
|
-
else {
|
|
193
|
-
stop = start + end;
|
|
194
|
-
}
|
|
195
|
-
if (nodes.oscillatorLFO) {
|
|
196
|
-
nodes.oscillatorLFO.stop(stop);
|
|
197
|
-
}
|
|
198
|
-
if (props.oscillator.envelope) {
|
|
199
|
-
const amount = fv * (Math.pow(2.0, props.oscillator.envelope.amount / 12.0) - 1.0);
|
|
200
|
-
stopEnvelope(nodes.oscillator.frequency, fv, amount, props.oscillator.envelope.ADSR);
|
|
201
|
-
}
|
|
202
|
-
if (props.amp.envelope) {
|
|
203
|
-
stopEnvelope(nodes.amp.gain, 0.0, props.amp.envelope.amount, props.amp.envelope.ADSR);
|
|
204
|
-
}
|
|
205
|
-
nodes.oscillator.stop(stop);
|
|
206
|
-
setTimeout(() => {
|
|
207
|
-
var _a, _b, _c, _d, _e;
|
|
208
|
-
nodes.oscillator.disconnect();
|
|
209
|
-
nodes.amp.disconnect();
|
|
210
|
-
nodes.target.disconnect();
|
|
211
|
-
(_a = nodes.oscillatorLFO) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
212
|
-
(_b = nodes.oscillatorLFODepth) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
213
|
-
(_c = nodes.filter) === null || _c === void 0 ? void 0 : _c.disconnect();
|
|
214
|
-
(_d = nodes.convolver) === null || _d === void 0 ? void 0 : _d.disconnect();
|
|
215
|
-
(_e = nodes.convolverDepth) === null || _e === void 0 ? void 0 : _e.disconnect();
|
|
216
|
-
}, 2000);
|
|
217
|
-
}
|
|
218
|
-
function stopEnvelope(param, base, amount, ADSR) {
|
|
219
|
-
const end = dv > 0 ? dv : (context.currentTime - start);
|
|
220
|
-
const rate = ADSR[0] === 0.0 ? 1.0 : Math.min(end / (ADSR[0] / 1000), 1.0);
|
|
221
|
-
if (rate < 1.0) {
|
|
222
|
-
param.cancelScheduledValues(start);
|
|
223
|
-
param.setValueAtTime(base, start);
|
|
224
|
-
param.linearRampToValueAtTime(base + amount * rate, start + ADSR[0] / 1000 * rate);
|
|
225
|
-
param.linearRampToValueAtTime(base + amount * rate * ADSR[2], start + (ADSR[0] + ADSR[1]) / 1000 * rate);
|
|
226
|
-
}
|
|
227
|
-
param.linearRampToValueAtTime(base + amount * rate * ADSR[2], start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate, dv));
|
|
228
|
-
param.linearRampToValueAtTime(base, start + Math.max((ADSR[0] + ADSR[1]) / 1000 * rate, end) + ADSR[3] / 1000);
|
|
229
|
-
}
|
|
230
|
-
function startEnvelope(param, base, amount, ADSR) {
|
|
231
|
-
param.value = base;
|
|
232
|
-
param.setValueAtTime(base, start);
|
|
233
|
-
param.linearRampToValueAtTime(base + amount, start + ADSR[0] / 1000);
|
|
234
|
-
param.linearRampToValueAtTime(base + amount * ADSR[2], start + (ADSR[0] + ADSR[1]) / 1000);
|
|
235
|
-
}
|
|
236
|
-
function impulseResponse({ time, decay = 2.0 }) {
|
|
237
|
-
const length = context.sampleRate * time / 1000;
|
|
238
|
-
const impulse = context.createBuffer(2, length, context.sampleRate);
|
|
239
|
-
const ch0 = impulse.getChannelData(0);
|
|
240
|
-
const ch1 = impulse.getChannelData(1);
|
|
241
|
-
for (let i = 0; i < length; i++) {
|
|
242
|
-
ch0[i] = (2 * Math.random() - 1) * Math.pow(1 - i / length, decay);
|
|
243
|
-
ch1[i] = (2 * Math.random() - 1) * Math.pow(1 - i / length, decay);
|
|
244
|
-
}
|
|
245
|
-
return impulse;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
export { xaudio as default };
|