@marmooo/midy 0.5.0 → 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 +17 -2
- package/esm/midy-GM1.d.ts +3 -2
- package/esm/midy-GM1.d.ts.map +1 -1
- package/esm/midy-GM1.js +59 -67
- package/esm/midy-GM2.d.ts +8 -18
- package/esm/midy-GM2.d.ts.map +1 -1
- package/esm/midy-GM2.js +117 -158
- package/esm/midy-GMLite.d.ts +3 -2
- package/esm/midy-GMLite.d.ts.map +1 -1
- package/esm/midy-GMLite.js +60 -68
- package/esm/midy.d.ts +8 -18
- package/esm/midy.d.ts.map +1 -1
- package/esm/midy.js +121 -161
- package/esm/reverb.d.ts +58 -0
- package/esm/reverb.d.ts.map +1 -0
- package/esm/reverb.js +389 -0
- package/package.json +1 -1
- package/script/midy-GM1.d.ts +3 -2
- package/script/midy-GM1.d.ts.map +1 -1
- package/script/midy-GM1.js +59 -67
- package/script/midy-GM2.d.ts +8 -18
- package/script/midy-GM2.d.ts.map +1 -1
- package/script/midy-GM2.js +117 -158
- package/script/midy-GMLite.d.ts +3 -2
- package/script/midy-GMLite.d.ts.map +1 -1
- package/script/midy-GMLite.js +60 -68
- package/script/midy.d.ts +8 -18
- package/script/midy.d.ts.map +1 -1
- package/script/midy.js +121 -161
- package/script/reverb.d.ts +58 -0
- package/script/reverb.d.ts.map +1 -0
- package/script/reverb.js +405 -0
package/README.md
CHANGED
|
@@ -94,9 +94,9 @@ midy.addEventListener("resumed", func);
|
|
|
94
94
|
midy.addEventListener("seeked", func);
|
|
95
95
|
```
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
### Cache Mode
|
|
98
98
|
|
|
99
|
-
- "none" -for full real-time control (dynamic CC, LFO, pitch)
|
|
99
|
+
- "none" - for full real-time control (dynamic CC, LFO, pitch)
|
|
100
100
|
- "ads" - for real-time playback with higher cache hit rate
|
|
101
101
|
- "adsr" - for real-time playback with accurate release envelope
|
|
102
102
|
- "note" - for efficient playback when note behavior is fixed
|
|
@@ -104,6 +104,21 @@ midy.addEventListener("seeked", func);
|
|
|
104
104
|
|
|
105
105
|
```
|
|
106
106
|
const midy = new Midy(audioContext, { cacheMode: "note" });
|
|
107
|
+
midy.cacheMode = "audio";
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Reverb Mode
|
|
111
|
+
|
|
112
|
+
- "Convolution" - Convolution Reverb
|
|
113
|
+
- "Schroeder" - Schroeder (1962)
|
|
114
|
+
- "Moorer" - Moorer (1979)
|
|
115
|
+
- "FDN" - FDN (1992)
|
|
116
|
+
- "Dattorro" - Dattorro (1997)
|
|
117
|
+
- "Freeverb" - Freeverb (1999)
|
|
118
|
+
- "VelvetNoise" - Velvet Noise Reverb (2012)
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
midy.setReverbEffect("FDN");
|
|
107
122
|
```
|
|
108
123
|
|
|
109
124
|
### MIDI Message
|
package/esm/midy-GM1.d.ts
CHANGED
|
@@ -130,7 +130,7 @@ export class MidyGM1 extends EventTarget {
|
|
|
130
130
|
getAudioBuffer(channel: any, note: any, realtime: any): Promise<any>;
|
|
131
131
|
getAdsCachedBuffer(channel: any, note: any, audioBufferId: any, realtime: any): Promise<any>;
|
|
132
132
|
getAdsrCachedBuffer(note: any, audioBufferId: any): Promise<any>;
|
|
133
|
-
getFullCachedBuffer(note: any, audioBufferId: any): Promise<any>;
|
|
133
|
+
getFullCachedBuffer(channel: any, note: any, audioBufferId: any): Promise<any>;
|
|
134
134
|
setNoteAudioNode(channel: any, note: any, realtime: any): Promise<any>;
|
|
135
135
|
handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
136
136
|
setNoteRouting(channelNumber: any, note: any, startTime: any): void;
|
|
@@ -209,7 +209,8 @@ export class MidyGM1 extends EventTarget {
|
|
|
209
209
|
scheduleTask(callback: any, scheduleTime: any): Promise<any>;
|
|
210
210
|
}
|
|
211
211
|
declare class Channel {
|
|
212
|
-
constructor(audioNodes: any, settings: any);
|
|
212
|
+
constructor(channelNumber: any, audioNodes: any, settings: any);
|
|
213
|
+
channelNumber: number;
|
|
213
214
|
isDrum: boolean;
|
|
214
215
|
programNumber: number;
|
|
215
216
|
scheduleIndex: number;
|
package/esm/midy-GM1.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy-GM1.d.ts","sourceRoot":"","sources":["../src/midy-GM1.js"],"names":[],"mappings":"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"}
|
package/esm/midy-GM1.js
CHANGED
|
@@ -160,7 +160,13 @@ class Note {
|
|
|
160
160
|
}
|
|
161
161
|
}
|
|
162
162
|
class Channel {
|
|
163
|
-
constructor(audioNodes, settings) {
|
|
163
|
+
constructor(channelNumber, audioNodes, settings) {
|
|
164
|
+
Object.defineProperty(this, "channelNumber", {
|
|
165
|
+
enumerable: true,
|
|
166
|
+
configurable: true,
|
|
167
|
+
writable: true,
|
|
168
|
+
value: 0
|
|
169
|
+
});
|
|
164
170
|
Object.defineProperty(this, "isDrum", {
|
|
165
171
|
enumerable: true,
|
|
166
172
|
configurable: true,
|
|
@@ -245,6 +251,7 @@ class Channel {
|
|
|
245
251
|
writable: true,
|
|
246
252
|
value: null
|
|
247
253
|
});
|
|
254
|
+
this.channelNumber = channelNumber;
|
|
248
255
|
Object.assign(this, audioNodes);
|
|
249
256
|
Object.assign(this, settings);
|
|
250
257
|
this.state = new ControllerState();
|
|
@@ -874,6 +881,8 @@ export class MidyGM1 extends EventTarget {
|
|
|
874
881
|
return;
|
|
875
882
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
876
883
|
const voice = soundFont.getVoice(bank, programNumber, noteNumber, velocity);
|
|
884
|
+
if (!voice)
|
|
885
|
+
return;
|
|
877
886
|
const { instrument, sampleID } = voice.generators;
|
|
878
887
|
return soundFontIndex * (2 ** 31) + instrument * (2 ** 24) +
|
|
879
888
|
(sampleID << 8);
|
|
@@ -890,7 +899,7 @@ export class MidyGM1 extends EventTarget {
|
|
|
890
899
|
}
|
|
891
900
|
createChannels(audioContext) {
|
|
892
901
|
const settings = this.constructor.channelSettings;
|
|
893
|
-
return Array.from({ length: this.numChannels }, () => new Channel(this.createChannelAudioNodes(audioContext), settings));
|
|
902
|
+
return Array.from({ length: this.numChannels }, (_, ch) => new Channel(ch, this.createChannelAudioNodes(audioContext), settings));
|
|
894
903
|
}
|
|
895
904
|
decodeOggVorbis(sample) {
|
|
896
905
|
const task = decoderQueue.then(async () => {
|
|
@@ -1356,6 +1365,7 @@ export class MidyGM1 extends EventTarget {
|
|
|
1356
1365
|
continue;
|
|
1357
1366
|
const soundFont = this.soundFonts[soundFontIndex];
|
|
1358
1367
|
const fakeChannel = {
|
|
1368
|
+
channelNumber: ch,
|
|
1359
1369
|
state: { array: renderControllerStates[ch].slice() },
|
|
1360
1370
|
programNumber,
|
|
1361
1371
|
isDrum,
|
|
@@ -1674,25 +1684,29 @@ export class MidyGM1 extends EventTarget {
|
|
|
1674
1684
|
const volHold = volAttack + voiceParams.volHold;
|
|
1675
1685
|
const decayDuration = voiceParams.volDecay;
|
|
1676
1686
|
const adsDuration = volHold + decayDuration * decayCurve * 5;
|
|
1677
|
-
const
|
|
1678
|
-
const
|
|
1687
|
+
const sampleLoopStart = voiceParams.loopStart / voiceParams.sampleRate;
|
|
1688
|
+
const sampleLoopDuration = isLoop
|
|
1679
1689
|
? (voiceParams.loopEnd - voiceParams.loopStart) / voiceParams.sampleRate
|
|
1680
1690
|
: 0;
|
|
1681
|
-
const
|
|
1682
|
-
|
|
1691
|
+
const playbackRate = voiceParams.playbackRate;
|
|
1692
|
+
const outputLoopStart = sampleLoopStart / playbackRate;
|
|
1693
|
+
const outputLoopDuration = sampleLoopDuration / playbackRate;
|
|
1694
|
+
const loopCount = isLoop && adsDuration > outputLoopStart
|
|
1695
|
+
? Math.ceil((adsDuration - outputLoopStart) / outputLoopDuration)
|
|
1683
1696
|
: 0;
|
|
1684
|
-
const alignedLoopStart =
|
|
1697
|
+
const alignedLoopStart = outputLoopStart + loopCount * outputLoopDuration;
|
|
1685
1698
|
const renderDuration = isLoop
|
|
1686
|
-
? alignedLoopStart +
|
|
1687
|
-
: audioBuffer.duration;
|
|
1688
|
-
const
|
|
1699
|
+
? alignedLoopStart + outputLoopDuration
|
|
1700
|
+
: audioBuffer.duration / playbackRate;
|
|
1701
|
+
const sampleRate = this.audioContext.sampleRate;
|
|
1702
|
+
const offlineContext = new OfflineAudioContext(audioBuffer.numberOfChannels, Math.ceil(renderDuration * sampleRate), sampleRate);
|
|
1689
1703
|
const bufferSource = new AudioBufferSourceNode(offlineContext);
|
|
1690
1704
|
bufferSource.buffer = audioBuffer;
|
|
1691
|
-
bufferSource.playbackRate.value =
|
|
1705
|
+
bufferSource.playbackRate.value = playbackRate;
|
|
1692
1706
|
bufferSource.loop = isLoop;
|
|
1693
1707
|
if (isLoop) {
|
|
1694
|
-
bufferSource.loopStart =
|
|
1695
|
-
bufferSource.loopEnd =
|
|
1708
|
+
bufferSource.loopStart = sampleLoopStart;
|
|
1709
|
+
bufferSource.loopEnd = sampleLoopStart + sampleLoopDuration;
|
|
1696
1710
|
}
|
|
1697
1711
|
const initialFreq = this.clampCutoffFrequency(this.centToHz(voiceParams.initialFilterFc));
|
|
1698
1712
|
const filterEnvelopeNode = new BiquadFilterNode(offlineContext, {
|
|
@@ -1724,7 +1738,7 @@ export class MidyGM1 extends EventTarget {
|
|
|
1724
1738
|
isLoop,
|
|
1725
1739
|
adsDuration,
|
|
1726
1740
|
loopStart: alignedLoopStart,
|
|
1727
|
-
loopDuration,
|
|
1741
|
+
loopDuration: outputLoopDuration,
|
|
1728
1742
|
});
|
|
1729
1743
|
}
|
|
1730
1744
|
async createAdsrRenderedBuffer(note, voiceParams, audioBuffer, noteDuration) {
|
|
@@ -1822,7 +1836,7 @@ export class MidyGM1 extends EventTarget {
|
|
|
1822
1836
|
}
|
|
1823
1837
|
async createFullRenderedBuffer(channel, note, voiceParams, noteDuration, noteEvent = {}) {
|
|
1824
1838
|
const { startTime: noteStartTime = 0, events: noteEvents = [] } = noteEvent;
|
|
1825
|
-
const ch =
|
|
1839
|
+
const ch = channel.channelNumber;
|
|
1826
1840
|
const releaseEndDuration = voiceParams.volRelease * releaseCurve * 5;
|
|
1827
1841
|
const totalDuration = noteDuration + releaseEndDuration;
|
|
1828
1842
|
const sampleRate = this.audioContext.sampleRate;
|
|
@@ -1871,7 +1885,7 @@ export class MidyGM1 extends EventTarget {
|
|
|
1871
1885
|
const audioBufferId = this.getVoiceId(channel, noteNumber, velocity);
|
|
1872
1886
|
if (!realtime) {
|
|
1873
1887
|
if (cacheMode === "note") {
|
|
1874
|
-
return await this.getFullCachedBuffer(note, audioBufferId);
|
|
1888
|
+
return await this.getFullCachedBuffer(channel, note, audioBufferId);
|
|
1875
1889
|
}
|
|
1876
1890
|
else if (cacheMode === "adsr") {
|
|
1877
1891
|
return await this.getAdsrCachedBuffer(note, audioBufferId);
|
|
@@ -1962,7 +1976,7 @@ export class MidyGM1 extends EventTarget {
|
|
|
1962
1976
|
durationMap.set(cacheKey, renderPromise);
|
|
1963
1977
|
return await renderPromise;
|
|
1964
1978
|
}
|
|
1965
|
-
async getFullCachedBuffer(note, audioBufferId) {
|
|
1979
|
+
async getFullCachedBuffer(channel, note, audioBufferId) {
|
|
1966
1980
|
const voiceParams = note.voiceParams;
|
|
1967
1981
|
const timelineIndex = note.timelineIndex;
|
|
1968
1982
|
const noteEvent = this.noteOnEvents.get(timelineIndex);
|
|
@@ -1987,7 +2001,7 @@ export class MidyGM1 extends EventTarget {
|
|
|
1987
2001
|
}
|
|
1988
2002
|
const renderPromise = (async () => {
|
|
1989
2003
|
try {
|
|
1990
|
-
const rendered = await this.createFullRenderedBuffer(
|
|
2004
|
+
const rendered = await this.createFullRenderedBuffer(channel, note, voiceParams, noteDuration, noteEvent);
|
|
1991
2005
|
durationMap.set(cacheKey, rendered);
|
|
1992
2006
|
return rendered;
|
|
1993
2007
|
}
|
|
@@ -2014,7 +2028,6 @@ export class MidyGM1 extends EventTarget {
|
|
|
2014
2028
|
note.renderedBuffer = isRendered ? audioBuffer : null;
|
|
2015
2029
|
note.bufferSource = this.createBufferSource(voiceParams, audioBuffer);
|
|
2016
2030
|
note.volumeNode = new GainNode(audioContext);
|
|
2017
|
-
note.volumeNode.gain.setValueAtTime(1, now);
|
|
2018
2031
|
const cacheMode = this.cacheMode;
|
|
2019
2032
|
const isFullCached = isRendered && audioBuffer.isFull === true;
|
|
2020
2033
|
if (cacheMode === "none") {
|
|
@@ -2091,9 +2104,6 @@ export class MidyGM1 extends EventTarget {
|
|
|
2091
2104
|
startTime = this.audioContext.currentTime;
|
|
2092
2105
|
const note = new Note(noteNumber, velocity, startTime);
|
|
2093
2106
|
note.channel = channelNumber;
|
|
2094
|
-
const channel = this.channels[channelNumber];
|
|
2095
|
-
note.index = channel.scheduledNotes.length;
|
|
2096
|
-
channel.scheduledNotes.push(note);
|
|
2097
2107
|
return note;
|
|
2098
2108
|
}
|
|
2099
2109
|
async setupNote(channelNumber, note, startTime) {
|
|
@@ -2116,6 +2126,8 @@ export class MidyGM1 extends EventTarget {
|
|
|
2116
2126
|
note.voice = soundFont.getVoice(bank, programNumber, note.noteNumber, note.velocity);
|
|
2117
2127
|
if (!note.voice)
|
|
2118
2128
|
return;
|
|
2129
|
+
note.index = channel.scheduledNotes.length;
|
|
2130
|
+
channel.scheduledNotes.push(note);
|
|
2119
2131
|
await this.setNoteAudioNode(channel, note, realtime);
|
|
2120
2132
|
this.setNoteRouting(channelNumber, note, startTime);
|
|
2121
2133
|
note.resolveReady();
|
|
@@ -2161,18 +2173,8 @@ export class MidyGM1 extends EventTarget {
|
|
|
2161
2173
|
const volRelease = endTime + volDuration;
|
|
2162
2174
|
note.volumeNode.gain
|
|
2163
2175
|
.cancelScheduledValues(endTime)
|
|
2164
|
-
.setValueAtTime(1, endTime)
|
|
2165
2176
|
.setTargetAtTime(0, endTime, volDuration * releaseCurve);
|
|
2166
|
-
|
|
2167
|
-
this.scheduleTask(() => {
|
|
2168
|
-
note.bufferSource.loop = false;
|
|
2169
|
-
note.bufferSource.stop(volRelease);
|
|
2170
|
-
this.disconnectNote(note);
|
|
2171
|
-
channel.scheduledNotes[note.index] = undefined;
|
|
2172
|
-
this.releaseFullCache(note);
|
|
2173
|
-
resolve();
|
|
2174
|
-
}, volRelease);
|
|
2175
|
-
});
|
|
2177
|
+
note.bufferSource.stop(volRelease);
|
|
2176
2178
|
}
|
|
2177
2179
|
else {
|
|
2178
2180
|
const now = this.audioContext.currentTime;
|
|
@@ -2182,15 +2184,16 @@ export class MidyGM1 extends EventTarget {
|
|
|
2182
2184
|
this.releaseFullCache(note);
|
|
2183
2185
|
return Promise.resolve();
|
|
2184
2186
|
}
|
|
2185
|
-
|
|
2186
|
-
this.scheduleTask(() => {
|
|
2187
|
-
this.disconnectNote(note);
|
|
2188
|
-
channel.scheduledNotes[note.index] = undefined;
|
|
2189
|
-
this.releaseFullCache(note);
|
|
2190
|
-
resolve();
|
|
2191
|
-
}, naturalEndTime);
|
|
2192
|
-
});
|
|
2187
|
+
note.bufferSource.stop(naturalEndTime);
|
|
2193
2188
|
}
|
|
2189
|
+
return new Promise((resolve) => {
|
|
2190
|
+
note.bufferSource.onended = () => {
|
|
2191
|
+
this.disconnectNote(note);
|
|
2192
|
+
channel.scheduledNotes[note.index] = undefined;
|
|
2193
|
+
this.releaseFullCache(note);
|
|
2194
|
+
resolve();
|
|
2195
|
+
};
|
|
2196
|
+
});
|
|
2194
2197
|
}
|
|
2195
2198
|
const volDuration = note.voiceParams.volRelease;
|
|
2196
2199
|
const volRelease = endTime + volDuration;
|
|
@@ -2211,45 +2214,33 @@ export class MidyGM1 extends EventTarget {
|
|
|
2211
2214
|
const noteOffTime = note.startTime + (rb.noteDuration ?? 0);
|
|
2212
2215
|
const isEarlyCut = endTime < noteOffTime;
|
|
2213
2216
|
if (isEarlyCut) {
|
|
2214
|
-
const volRelease = endTime + volDuration;
|
|
2215
2217
|
note.volumeNode.gain
|
|
2216
2218
|
.cancelScheduledValues(endTime)
|
|
2217
|
-
.setValueAtTime(1, endTime)
|
|
2218
2219
|
.setTargetAtTime(0, endTime, volDuration * releaseCurve);
|
|
2219
|
-
|
|
2220
|
-
this.scheduleTask(() => {
|
|
2221
|
-
note.bufferSource.stop(volRelease);
|
|
2222
|
-
this.disconnectNote(note);
|
|
2223
|
-
channel.scheduledNotes[note.index] = undefined;
|
|
2224
|
-
resolve();
|
|
2225
|
-
}, volRelease);
|
|
2226
|
-
});
|
|
2220
|
+
note.bufferSource.stop(volRelease);
|
|
2227
2221
|
}
|
|
2228
2222
|
else {
|
|
2229
|
-
|
|
2230
|
-
this.scheduleTask(() => {
|
|
2231
|
-
note.bufferSource.stop();
|
|
2232
|
-
this.disconnectNote(note);
|
|
2233
|
-
channel.scheduledNotes[note.index] = undefined;
|
|
2234
|
-
resolve();
|
|
2235
|
-
}, naturalEndTime);
|
|
2236
|
-
});
|
|
2223
|
+
note.bufferSource.stop(naturalEndTime);
|
|
2237
2224
|
}
|
|
2225
|
+
return new Promise((resolve) => {
|
|
2226
|
+
note.bufferSource.onended = () => {
|
|
2227
|
+
this.disconnectNote(note);
|
|
2228
|
+
channel.scheduledNotes[note.index] = undefined;
|
|
2229
|
+
resolve();
|
|
2230
|
+
};
|
|
2231
|
+
});
|
|
2238
2232
|
}
|
|
2239
2233
|
note.volumeNode.gain
|
|
2240
2234
|
.cancelScheduledValues(endTime)
|
|
2241
|
-
.setValueAtTime(1, endTime)
|
|
2242
2235
|
.setTargetAtTime(0, endTime, volDuration * releaseCurve);
|
|
2243
2236
|
}
|
|
2237
|
+
note.bufferSource.stop(volRelease);
|
|
2244
2238
|
return new Promise((resolve) => {
|
|
2245
|
-
|
|
2246
|
-
const bufferSource = note.bufferSource;
|
|
2247
|
-
bufferSource.loop = false;
|
|
2248
|
-
bufferSource.stop(volRelease);
|
|
2239
|
+
note.bufferSource.onended = () => {
|
|
2249
2240
|
this.disconnectNote(note);
|
|
2250
2241
|
channel.scheduledNotes[note.index] = undefined;
|
|
2251
2242
|
resolve();
|
|
2252
|
-
}
|
|
2243
|
+
};
|
|
2253
2244
|
});
|
|
2254
2245
|
}
|
|
2255
2246
|
noteOff(channelNumber, noteNumber, _velocity, endTime, force) {
|
|
@@ -2805,9 +2796,10 @@ export class MidyGM1 extends EventTarget {
|
|
|
2805
2796
|
setMasterVolume(value, scheduleTime) {
|
|
2806
2797
|
if (!(0 <= scheduleTime))
|
|
2807
2798
|
scheduleTime = this.audioContext.currentTime;
|
|
2799
|
+
const timeConstant = this.perceptualSmoothingTime / 5; // 99.3% (5 * tau)
|
|
2808
2800
|
this.masterVolume.gain
|
|
2809
|
-
.
|
|
2810
|
-
.
|
|
2801
|
+
.cancelAndHoldAtTime(scheduleTime)
|
|
2802
|
+
.setTargetAtTime(value * value, scheduleTime, timeConstant);
|
|
2811
2803
|
}
|
|
2812
2804
|
handleSysEx(data, scheduleTime) {
|
|
2813
2805
|
switch (data[0]) {
|
package/esm/midy-GM2.d.ts
CHANGED
|
@@ -94,7 +94,7 @@ export class MidyGM2 extends EventTarget {
|
|
|
94
94
|
reverbEffect: {
|
|
95
95
|
input: any;
|
|
96
96
|
output: any;
|
|
97
|
-
}
|
|
97
|
+
};
|
|
98
98
|
chorusEffect: {
|
|
99
99
|
input: any;
|
|
100
100
|
output: any;
|
|
@@ -116,7 +116,7 @@ export class MidyGM2 extends EventTarget {
|
|
|
116
116
|
gainR: any;
|
|
117
117
|
merger: any;
|
|
118
118
|
};
|
|
119
|
-
createChannels(
|
|
119
|
+
createChannels(): Channel[];
|
|
120
120
|
decodeOggVorbis(sample: any): Promise<any>;
|
|
121
121
|
createAudioBuffer(voiceParams: any): Promise<any>;
|
|
122
122
|
isLoopDrum(channel: any, noteNumber: any): boolean;
|
|
@@ -148,24 +148,13 @@ export class MidyGM2 extends EventTarget {
|
|
|
148
148
|
currentTime(): number;
|
|
149
149
|
processScheduledNotes(channel: any, callback: any): Promise<void>;
|
|
150
150
|
processActiveNotes(channel: any, scheduleTime: any, callback: any): Promise<void>;
|
|
151
|
-
createConvolutionReverbImpulse(audioContext: any, decay: any, preDecay: any): any;
|
|
152
|
-
createConvolutionReverb(audioContext: any, impulse: any): {
|
|
153
|
-
input: any;
|
|
154
|
-
output: any;
|
|
155
|
-
convolverNode: any;
|
|
156
|
-
};
|
|
157
|
-
createCombFilter(audioContext: any, input: any, delay: any, feedback: any): any;
|
|
158
|
-
createAllpassFilter(audioContext: any, input: any, delay: any, feedback: any): any;
|
|
159
151
|
generateDistributedArray(center: any, count: any, varianceRatio?: number, randomness?: number): any[];
|
|
160
|
-
|
|
152
|
+
setReverbEffect(algorithm: any): void;
|
|
153
|
+
createReverbEffect(algorithm: any): {
|
|
161
154
|
input: any;
|
|
162
155
|
output: any;
|
|
163
156
|
};
|
|
164
|
-
|
|
165
|
-
input: any;
|
|
166
|
-
output: any;
|
|
167
|
-
} | undefined;
|
|
168
|
-
createChorusEffect(audioContext: any): {
|
|
157
|
+
createChorusEffect(): {
|
|
169
158
|
input: any;
|
|
170
159
|
output: any;
|
|
171
160
|
sendGain: any;
|
|
@@ -200,7 +189,7 @@ export class MidyGM2 extends EventTarget {
|
|
|
200
189
|
getAudioBuffer(channel: any, note: any, realtime: any): Promise<any>;
|
|
201
190
|
getAdsCachedBuffer(channel: any, note: any, audioBufferId: any, realtime: any): Promise<any>;
|
|
202
191
|
getAdsrCachedBuffer(channel: any, note: any, audioBufferId: any): Promise<any>;
|
|
203
|
-
getFullCachedBuffer(note: any, audioBufferId: any): Promise<any>;
|
|
192
|
+
getFullCachedBuffer(channel: any, note: any, audioBufferId: any): Promise<any>;
|
|
204
193
|
setNoteAudioNode(channel: any, note: any, realtime: any): Promise<any>;
|
|
205
194
|
handleExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
206
195
|
handleDrumExclusiveClass(note: any, channelNumber: any, startTime: any): void;
|
|
@@ -353,7 +342,8 @@ export class MidyGM2 extends EventTarget {
|
|
|
353
342
|
scheduleTask(callback: any, scheduleTime: any): Promise<any>;
|
|
354
343
|
}
|
|
355
344
|
declare class Channel {
|
|
356
|
-
constructor(audioNodes: any, settings: any);
|
|
345
|
+
constructor(channelNumber: any, audioNodes: any, settings: any);
|
|
346
|
+
channelNumber: number;
|
|
357
347
|
isDrum: boolean;
|
|
358
348
|
programNumber: number;
|
|
359
349
|
scheduleIndex: number;
|
package/esm/midy-GM2.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"midy-GM2.d.ts","sourceRoot":"","sources":["../src/midy-GM2.js"],"names":[],"mappings":"AA4TA;IAgEE;;;;;;;;;;;;;;MAcE;IAEF,6CAuBC;IAlGD,gCAAgC;IAChC,aAAa;IACb,yBAAqB;IACrB,2BAAuB;IACvB;;;;MAIE;IACF;;;;;;MAME;IACF,oBAAiB;IACjB,qBAAmB;IACnB,kBAAc;IACd,0BAAsB;IACtB,+BAA6B;IAC7B,0BAAwB;IACxB,kBAAc;IACd,mBAAiB;IACjB,kBAAc;IACd,mBAAe;IACf,kBAAgB;IAChB,0BAAuD;IACvD,4BAAyB;IACzB,0BAAuB;IACvB,kCAA+B;IAC/B,qBAAqC;IACrC,mBAAkB;IAClB,mBAAkB;IAClB,kBAAiB;IACjB,oBAAmB;IACnB,mBAAkB;IAClB,iCAA2C;IAC3C,cAAU;IACV,cAAa;IACb,iBAAY;IACZ,gBAAc;IACd,oBAAkB;IAClB,sBAAwB;IACxB,2BAAqC;IACrC,+BAEE;IAEF,8BAA2B;IAE3B,+BAA4B;IAC5B,4BAAyB;IACzB,8BAA2B;IAE3B,0BAA2B;IAC3B,qBAAoB;IACpB,4BAA6B;IAoB3B,kBAAgC;IAChC,eAAwD;IACxD,kBAA8C;IAC9C,eAAwD;IACxD,qBAGE;IACF,uBAAmD;IACnD;;;;;;;;;;;;MAA2D;IAC3D,6BAA+D;IAC/D,kCAAyE;IACzE,sBAAiD;IACjD,oBAAqC;IACrC;;;MAAkE;IAClE;;;;;;;;MAA6C;IAQ/C,mCASC;IAED,2DAYC;IAED,yCAmBC;IAED,oCAYC;IAED,6BAqJC;IAED,sBAuCC;IAED,6EAiBC;IAED;;;;MAWC;IAED,4BAQC;IAED,2CAsBC;IAED,kDA6BC;IAED,mDAIC;IAED,6FAqBC;IAED,gEA2DC;IAED,mCASC;IAED,uBAWC;IAED,yDA4CC;IAED,iCA4EC;IAED,2BAuFC;IAED,uDAEC;IAED,wDAEC;IAED,qCAMC;IAED;;;MAqFC;IAED,kGAeC;IAED,mGAeC;IAED,wEAQC;IAED,oCAqMC;IAED,uBAMC;IAED,sBAIC;IAED,uBAMC;IAED,wBAIC;IAED,0BAKC;IAED,8BAoBC;IAED,wBAYC;IAED,sBAOC;IAED,kEAWC;IAED,kFAYC;IAED,sGAcC;IAED,sCAIC;IAED;;;MA4DC;IAED;;;;;;;;MA2CC;IAED,8BAEC;IAED,8BAEC;IAED,4BAEC;IAED,qCAWC;IAED,2DASC;IAED,oDAEC;IAED,6CAIC;IAED,mDAIC;IAED,2CAoDC;IAED,8EASC;IAED,oEAiBC;IAED,sEASC;IAED,4DAMC;IAED,6EAOC;IAED,qDAkBC;IAED,6CAIC;IAED,8EAmBC;IAED,oEAgCC;IAED,kEAwBC;IAED,+DAgBC;IAED,gIAyEC;IAED,kIA0GC;IAED,gIA6DC;IAED,qEAwBC;IAED,6FAuCC;IAED,+EAgDC;IAED,+EA0CC;IAED,uEAqFC;IAED,0EAiBC;IAED,8EAoBC;IAED,oEAyBC;IAED,yFAQC;IAED,qFAKC;IAED,uEAiCC;IAED,gCAoBC;IAED,kCAWC;IAED,iEAkFC;IAED,4FAqBC;IAED,6CAUC;IAED,qDAUC;IAED,qFAeC;IAED,uFAkBC;IAED,+BAuBC;IAED,kDAOC;IAED,sBAEC;IAED,mFAcC;IAED,4EAYC;IAED,wFAGC;IAED,sEAWC;IAED,mEAaC;IAED,mEAYC;IAED,sEAMC;IAED,oEAQC;IAED,gEAyBC;IAED,gEAyBC;IAED,gCAKC;IAED,kDAKC;IAED,8CAOC;IAED,gEAMC;IAED;;;;;;;;;;;;MAwDC;IAED,oFAMC;IAED,6EAgCC;IAED,qCA2BC;IAED,+FAeC;IAED,+CAEC;IAED,wDAWC;IAED,4EAMC;IAED,wDAeC;IAED,2EAMC;IAED,mEAKC;IAED,mDAQC;IAED;;;MAMC;IAED,gEAWC;IAED,uEAKC;IAED,+CAEC;IAED,sEAGC;IAED,2DAWC;IAED,4EAoBC;IAED,yEAgBC;IAED,+CAEC;IAED,uEAMC;IAED,2EAkBC;IAED,oDAEC;IAED,0EAeC;IAED,sFAQC;IAED,sFAQC;IAED,kFAeC;IAED,2DAMC;IAED,uDAuBC;IAED,gDAEC;IAED,gDAEC;IAED,sEAGC;IAED,qEAKC;IAED,2EAWC;IAED,iEAMC;IAED,uEASC;IAED,mEAKC;IAED,yEASC;IAED,2EAKC;IAED,iFAMC;IAED,gFAGC;IAED,6CAsBC;IAGD,8EAoCC;IAED,gFAGC;IAED,iEAEC;IAED,gEAEC;IAED,gEAIC;IAED,gEAIC;IAED,+EAgCC;IAED,qCAaC;IAED,qCAaC;IAED,4EAwCC;IAED,4DAGC;IAED,qDAMC;IAED,gEAIC;IAED,yDAYC;IAED,kEAGC;IAED,2DAYC;IAED,sEAeC;IAED,4CAOC;IAED,+BAIC;IAED,qDAiBC;IAED,gCAGC;IAED,kCAEC;IA6BD,4CAEC;IAED,+DAaC;IAED,kDAiBC;IAED,2GAKC;IAED,sDAIC;IAED,qCAEC;IAED,uDAMC;IAED,sCAEC;IAED,uDASC;IAED,sCAEC;IAED,2DAqBC;IAED,0CAEC;IAED,mCAeC;IAED,2FAgBC;IAED,wDAEC;IAED,+DAGC;IAED,qEASC;IAED,uEAOC;IAED,6CAEC;IAED,iDAEC;IAED,6CAEC;IAED,iDAEC;IAED,0CAEC;IAED,uCAEC;IAED,wCAEC;IAED,2CAEC;IAED,8BAyBC;IAED,0EAQC;IAED,4EAOC;IAED,qFASC;IAED,+DAEC;IAED,wEAcC;IAED,6DAiBC;IAED,yEAIC;IAED,0CAmBC;IAED,yEAcC;IAED,gDAYC;IAGD,6DAgBC;CACF;AAxhID;IA2BE,gEAKC;IA/BD,sBAAkB;IAClB,gBAAe;IACf,sBAAkB;IAClB,sBAAkB;IAClB,eAAW;IACX,gBAAc;IACd,gBAAY;IACZ,gBAAY;IACZ,gBAAY;IACZ,eAAa;IACb,eAAa;IACb,cAAa;IACb,6BAA0B;IAC1B,mBAAe;IACf,qBAAiB;IACjB,sBAAoB;IACpB,oBAAkB;IAClB,sBAAoB;IACpB,qCAAmD;IACnD,+CAA2C;IAC3C,6CAA4D;IAC5D,sCAAkD;IAClD,sBAAgC;IAChC,sBAAgC;IAChC,0BAA2B;IAMzB,uBAAkC;IAGpC,mCAEC;IAED,mBAKC;CACF;AAuID;IAUE,oCASC;IAlBD,YAAO;IACP,YAAO;IACP,YAAO;IACP,iBAAY;IACZ,eAAU;IACV,kBAAa;IACb,kBAAa;IACb,qBAAgB;CAYjB;AAvOD;IAsBE,4DAOC;IA5BD,WAAM;IACN,iBAAY;IACZ,yBAAyB;IACzB,cAAW;IACX,gBAAe;IACf,kBAAa;IACb,oBAAqB;IACrB,qBAAsB;IACtB,uBAAwB;IACxB,wBAAmB;IACnB,wBAAmB;IACnB,YAAO;IACP,mBAAc;IACd,sBAAiB;IACjB,oBAAe;IACf,YAAO;IACP,mBAAc;IACd,gBAAW;IACX,gBAAW;IACX,6BAA0B;IAGxB,gBAA4B;IAC5B,cAAwB;IACxB,eAA0B;IAC1B,oBAEE;IADA,mCAA2B;CAGhC;AAsHD;IACE,iCAA8B;CAa/B"}
|