midi-audio-player 1.1.2 → 2.0.0

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/downloader.js DELETED
@@ -1,33 +0,0 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
-
4
-
5
- export async function downloadWebAudioFont(id, filename) {
6
- const cleanFilename = filename.endsWith('.json') ? filename : `${filename}.json`;
7
- const destPath = path.join(process.cwd(), cleanFilename);
8
- const url = `https://surikov.github.io/webaudiofontdata/sound/${id}.js`;
9
-
10
- try {
11
- console.log(`📡 Téléchargement de : ${id}...`);
12
- const response = await fetch(url);
13
- if (!response.ok) throw new Error(`Erreur HTTP: ${response.status} (Vérifiez l'ID)`);
14
-
15
- const rawContent = await response.text();
16
- const firstBrace = rawContent.indexOf('{');
17
- const lastBrace = rawContent.lastIndexOf('}');
18
-
19
- if (firstBrace === -1 || lastBrace === -1) throw new Error("Format de fichier invalide : structure d'objet introuvable.");
20
-
21
- const objectString = rawContent.substring(firstBrace, lastBrace + 1);
22
- const data = new Function(`return ${objectString}`)();
23
- await fs.mkdir(path.dirname(destPath), { recursive: true });
24
- await fs.writeFile(destPath, JSON.stringify(data, null, 2));
25
-
26
- console.log(`✅ Terminé ! Fichier créé : ${destPath}`);
27
- return data;
28
-
29
- } catch (error) {
30
- console.error(`❌ Échec : ${error.message}`);
31
- throw error;
32
- }
33
- }
@@ -1,116 +0,0 @@
1
- {
2
- "zones": [
3
- {
4
- "midi": 81,
5
- "originalPitch": 4200,
6
- "keyRangeLow": 0,
7
- "keyRangeHigh": 43,
8
- "loopStart": 256,
9
- "loopEnd": 768,
10
- "coarseTune": 0,
11
- "fineTune": 0,
12
- "sampleRate": 48000,
13
- "ahdsr": false,
14
- "file": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU3LjcyLjEwMQAAAAAAAAAAAAAA//tUwAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAAGAACgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg//////////////////////////////////////////////////////////////////8AAAAATGF2YzU3Ljk2AAAAAAAAAAAAAAAAJALAAAAAAAAABgA5CeiPAAAAAAAAAAAAAAAAAAAA//vUxAAAB+gfQ1TwACTywCx/NYAJAABZOW7fg6F8L8A3AOwb5L2e7x5R5EoCADB8HwfPxACAYrB8H8oCDsHw/lAQdlwPqDHh/UCEp4fhiU8/ynv6BAGOZS1NzNUNm83W5HHJGz4Kk0TfzwzSZu8CgJ3TZ11pu3hi1hoxY8qMFcPAcBX40CM1RcwUo9EFQgiY2VPldy90c24GUwVQROZnA0ZXohQyMsyIBlAWEQK/zrsHfSBGmF4i+yiKKKNrP5FDrYJM+8XdeIRR1FaEwk0mLq5Upl0G35bBliJz8DxCcgSVtAYMpU27BVbW0tSXOzHsLU+88MTkCQ3PwO05aTrtqwF1G2YFHc7M1hamc5RYnJXbn6S9OU7L2apytcaEpk5bQVbXIszWrUzuzNatW5HKL05K+z9Jyip+vcyqG3yZTDELa1DcIazEIXV3jW1lV3jW1lV7h/M/7h/M/7h/9/+f/f/n/3/58qr2JTUtyqvYlNy3TXbFLct012xS3Kemu0lLWp6arSexu7G62Ja2Ja2Ja0QsKrWx13Wb36/a/7/ew5kMjLhQNcmAxqICUIjQsMqB4zeSzGokEALDBOxI2OrTTJJMLBUwcCQYAVMDdlQ0A6Zkis4q5jIAQzknMdGQMBLAltWVxZrJm4ma0hGaGCmrpKmfS87RrhMci3muq5p4+b4wKbPCqVlsBQHbcmCKhmxoZcGGmnZmJeZOEmiGS7nGjrWX5mn+j92HZJcMqKDIgYz0vMnJTHwUzYoMiIGdQNMuTIbj/U13dLc1aMqCjSTkzEvMpCTQjQy4qMkBjPTGR3X9pMI1N9q1aWtWpqtUyspMhBTOCwyYkMeAjNSsyUjMdATMCYyIgpZJZygGm+AqXGzWrWqtWzWrWjGgAy0lMhHwEXmVERjw4AigycfMdGwMVmSDhjQwCiSU1solVxiNamhqlpYZx3jllljvHLWWLlv/F3cfyKO+/8vfx/JY/7/y9/H8lj/v/Pv5Dk5D8bn4xGJyNxuf1llvHHWWW8cdZZbx//u0xLeAL2H/Z7nNkIFVkCR3sMAFx1llvHHWVbHGrllWAbmu1l2+wACIJmablgZJEkGiBRmRmRKSQMOakoAW1jywyxmXRDkBISlWnK1b7K0xdxcdLomjI+e1lat9latrlly7rLnrbVat8FFQgpgKeCmxTcgrgVVMQU1FMy45OS41VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
15
- "anchor": 0.00533333
16
- },
17
- {
18
- "midi": 81,
19
- "originalPitch": 5400,
20
- "keyRangeLow": 44,
21
- "keyRangeHigh": 55,
22
- "loopStart": 128,
23
- "loopEnd": 384,
24
- "coarseTune": 0,
25
- "fineTune": 0,
26
- "sampleRate": 48000,
27
- "ahdsr": false,
28
- "file": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU3LjcyLjEwMQAAAAAAAAAAAAAA//tUwAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAAEsADMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzM//////////////////////////////////////////////////////////////////8AAAAATGF2YzU3Ljk2AAAAAAAAAAAAAAAAJATAAAAAAAAABLAMEvhQAAAAAAAAAAAAAAAAAAAA//vUxAAACSwNaVQwACRXSC6/NYAIAAa9txyS8qHAwMDPlz5QEIIROfLn1AhBBy3lz/BCt5c/wQz5c/RBCXPlw/EEEHLPlz9EEOt8QQQcs+XPykQVh8uH4gcIHLD6w+JgcGkGbGakSCqjColKJDEMCR4mYQ8kQZ1UAiwCAIbAc4b1maEch6LAEVzMhwxuYQGCgLBWbmQSPi+kAzkOM6i/Ei2XrGgFiMbisXednEOO7NP9KJdLKedbxd7vvezh3pl/YdmreFqxnZjEgf+NyN/I1TXaWzqnqWqTOzTyyihuX0cMUlNa3S81TYWrGd63q/RRuno4xSUUbt3YzSYU1fuH8z/uH8zp6OMUlFK6e/KKTG5zKZy+ax/+4fzP+4fzP70rp78opL1PXv0lSzVy+tjjVyyrY41e4fzf91/N/3X83/dfzf91/N/3X5/3D+b/uv5v+6/m/7r/3/6/9/+sst446yy3jVyyrY41csq2ONXLKtjjVyyrKiLXdbW5JI24SEB1CQjhFAAXAIxdxbUKO0ekXEuKphJ5DkSgYKJVFFxQVwUwFDcRcUFcFcCjsTYoK4K4FHYmxQXwrgUdibFBfCvCjsTcRXhXhT8TcRXhXhT8TcRXhXhT8TcRXhXhT8TcakxBTUUzLjk5LjWqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//tkxMWDzQgxS7zzACgAADSAAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
29
- "anchor": 0.00266667
30
- },
31
- {
32
- "midi": 81,
33
- "originalPitch": 6600,
34
- "keyRangeLow": 56,
35
- "keyRangeHigh": 67,
36
- "loopStart": 64,
37
- "loopEnd": 192,
38
- "coarseTune": 0,
39
- "fineTune": 0,
40
- "sampleRate": 48000,
41
- "ahdsr": false,
42
- "file": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU3LjcyLjEwMQAAAAAAAAAAAAAA//tUwAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAAE4ADs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs//////////////////////////////////////////////////////////////////8AAAAATGF2YzU3Ljk2AAAAAAAAAAAAAAAAJAXAAAAAAAAABODQyktQAAAAAAAAAAAAAAAAAAAA//vkxAAABywBgbQAACYVyC6/P9AwKAASUcckkt4YWD4fLn1AhBCJz5c+oEFghy5/ghy5+cghy7+GKZd/DHLn1HIYk5d/DHL+6H5d5TOdLnbLTLKrBqyq+vlkqeD4lCzTAngBgvMYACAAGg+NZZoFwogYAGAZCwCsDgBJsJhRJLyYvYUvg4BLFAA9AKpqYxQCumE3hMhEBIkBkBLuNR5oOGzUbs0Jk7jR1yTFgpzGY2TMgWV8qtT4fmaf4xDKgxlNgzTGRZScSFbPVQxarGZbWMLiNMUC1MshXMJx+MRSeaZHnuceOvbGrV2ls6MOQUMAAnMDAzMMgRMAQkMCQufiahT9zMJfim7ul5rIDBEFgJBgHgoHQuBANAwFA1WkUbqzssyns944flv09UjUcU9kjkkk9UjZfjOyzKep8Z2kxucyq9+ax9JFNJNJNZNFNFNVNJNJNbKRRvGQxjKejfJ2Udq/9bf1darY41U0U0U1U0k0k+k0U0U+U0k0k+k0e5/zD+5/zD+5/zX93/Nf3f81/d////////7/9f+//X/v/1/7/9Jop8ppJpJ9Jop6qwppJ7KxJGp6qwpHKrKxI2qqqwo3KrKxI2qqq9RuVWV8jaqqr1G5TEFNRTMuOTkuNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVMQU1FMy45OS41VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUxNoDwAAB/hwAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
43
- "anchor": 0.00133333
44
- },
45
- {
46
- "midi": 81,
47
- "originalPitch": 7800,
48
- "keyRangeLow": 68,
49
- "keyRangeHigh": 79,
50
- "loopStart": 32,
51
- "loopEnd": 96,
52
- "coarseTune": 0,
53
- "fineTune": 0,
54
- "sampleRate": 48000,
55
- "ahdsr": false,
56
- "file": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU3LjcyLjEwMQAAAAAAAAAAAAAA//tUwAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAADwADm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm//////////////////////////////////////////////////////////////////8AAAAATGF2YzU3Ljk2AAAAAAAAAAAAAAAAJAZAAAAAAAAAA8CsVDBMAAAAAAAAAAAAAAAAAAAA//vExAAABmQBjaAAACGQBa9497AdtbAkWdckklxRyjhQ5BBYYqOFHRAXDHKHOGOUOcMco7nOJHawxynnOU5cMcHOXOcHOl3NXGMqsiEAqoMI8QsSUcIsgeiQgJISFCg5ABAyw+VQaiK8yY18FNiuxBUorwU0FdiC4ivimgrsQXEV4KaCuxBcTfBXAv4isTfiuBf6KxN+L4r8RUU3wXoL+JsU3wXoL+JsV3gvRSpMQU1FMy45OS41qqqqqqqqqqqqqqqqqqqqqqqq6goZoAABEOiCXDs8P3G8oicJAhZjVVVBlsStNFVVUT8StNVMQU1FMy45OS41VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUxOuDxEQnByYExigAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
57
- "anchor": 0.00066667
58
- },
59
- {
60
- "midi": 81,
61
- "originalPitch": 9000,
62
- "keyRangeLow": 80,
63
- "keyRangeHigh": 91,
64
- "loopStart": 16,
65
- "loopEnd": 48,
66
- "coarseTune": 0,
67
- "fineTune": 0,
68
- "sampleRate": 48000,
69
- "ahdsr": false,
70
- "file": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU3LjcyLjEwMQAAAAAAAAAAAAAA//tUwAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAADwADm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm//////////////////////////////////////////////////////////////////8AAAAATGF2YzU3Ljk2AAAAAAAAAAAAAAAAJAaAAAAAAAAAA8ChXkahAAAAAAAAAAAAAAAAAAAA//vExAAABkQDh+AAACGUhq9895iZZVlzMgFEYk0nBACCLQfD6gTB8/qBDBwMflC4f/gQMfqBMH/4OHP4Df+XBw5+UBN/6wJu1fapqZhlttyF2FyUYQ0W0QkFSJiRIro4TAYk8aQCAQCAKjiRIkSr+xQUFOBQUV/5BQU4KChv+CgoL4KCu/4QUN8KCn/8UFN8FFf/wgp/hQ3/8FBXYgoL/+FBX5BQ3/8FBfigopVMQU1FMy45OS41VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVMQU1FMy45OS41VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUxNoDwAAB/gAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
71
- "anchor": 0.00033333
72
- },
73
- {
74
- "midi": 81,
75
- "originalPitch": 10200,
76
- "keyRangeLow": 92,
77
- "keyRangeHigh": 103,
78
- "loopStart": 8,
79
- "loopEnd": 56,
80
- "coarseTune": 0,
81
- "fineTune": 0,
82
- "sampleRate": 48000,
83
- "ahdsr": false,
84
- "file": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU3LjcyLjEwMQAAAAAAAAAAAAAA//tUwAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAADwADm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm//////////////////////////////////////////////////////////////////8AAAAATGF2YzU3Ljk2AAAAAAAAAAAAAAAAJAaAAAAAAAAAA8AljJJeAAAAAAAAAAAAAAAAAAAA//vExAAABmgDh+AAACG7Cq649JmAh3unfGYwJRhSgQBBEXB8PjogBDn8EwfP6gQdicP/g4GOXB/lHfgmH905/UclwcOf/8oA/2r/qekIFM1D+AxK8OEgo9IhpLSJFdJaehzC3CbBom0GChJpEiRn/tRxIkSJT6OJJB3BUFXSwNB3BUFQVgqCoaqBoGsqd4iBo8oGgaTWCoaxEDR6VBUFTpUFQV//BoGoiBoO//rxKCv//iIGv/+WTEFNRTMuOTkuNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVMQU1FMy45OS41VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUxNoDwAAB/gAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
85
- "anchor": 0.00016667
86
- },
87
- {
88
- "midi": 81,
89
- "originalPitch": 11400,
90
- "keyRangeLow": 104,
91
- "keyRangeHigh": 115,
92
- "loopStart": 12,
93
- "loopEnd": 52,
94
- "coarseTune": 0,
95
- "fineTune": 0,
96
- "sampleRate": 48000,
97
- "ahdsr": false,
98
- "file": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU3LjcyLjEwMQAAAAAAAAAAAAAA//tUwAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAADwADm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubm//////////////////////////////////////////////////////////////////8AAAAATGF2YzU3Ljk2AAAAAAAAAAAAAAAAJAaAAAAAAAAAA8CNr1v4AAAAAAAAAAAAAAAAAAAA//vExAAAB1SVheCEbeI4SC349ApomIy4jYiPtA6x5AACs4xjvkAAPmMY/wAXzGMf4AL/X+IgG4PvwQOfIQQOZcH//wQlwfBA5/1h/iB2sP/17/1GMvIAEJ8BiUYMEW0NSAKQjJWj5HCbB/EGHqQ5m2plUuYL1WvVqeGZmb/VVVf9mZr/1VVX9hYGwKgFgbB9TCwNgbB8BG6lKUreYxjfKUrfQxvylK3oYxjeUKAgICJYoCAgICUvoYxvylL9DGN9SlL9P+UrfMYxjOoYCAgIUb6lL////////qUpSzASTEFNRTMuOTkuNaqqqqpMQU1FMy45OS41qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sUxNoDwAAB/gAAACAAADSAAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
99
- "anchor": 0.00008333
100
- },
101
- {
102
- "midi": 81,
103
- "originalPitch": 12600,
104
- "keyRangeLow": 116,
105
- "keyRangeHigh": 127,
106
- "loopStart": 6,
107
- "loopEnd": 42,
108
- "coarseTune": 0,
109
- "fineTune": 0,
110
- "sampleRate": 48000,
111
- "ahdsr": false,
112
- "file": "SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU3LjcyLjEwMQAAAAAAAAAAAAAA//tUwAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAACAAAEIADo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo//////////////////////////////////////////////////////////////////8AAAAATGF2YzU3Ljk2AAAAAAAAAAAAAAAAJAaQAAAAAAAABCDWHfeqAAAAAAAAAAAAAAAAAAAA//vUxAAACUUrfeCE1eMLSCx88a54l3jMh4t/trUApEAAAUAGYxja+WMYx/yAAH+MY/+AYx/4AAX8xjH/7/8AF//zHyAMdoIAgAAADAYWTt4IA/Kc5/////////y4Pg/v3FZropQkAAAEiDVBBhkjdBSk5JyDlHqDmWi+kJRsJiOZ69eva6x+zAQEBCm/9VVVb/9mVVL/9mZmP/6qqqn/8ZlVV/6zMzM3/VCgICanXX+5I2JRJHaana+SSNwIQEQAwAQAQEw6j5KBCASACACAKAmBGHcdr5RNR2jtJRsed/DkTU1NTra/3Oc5znf+1rWuc7/3Na1ra/9znOc7/9rWtc7/9zWta3/4c5znO/9rTU1NXOvbW4lDtDyHkPI7TqQIQAxMQU1FMy45OS41qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpMQU1FMy45OS41qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq//sUxNoDwAABpAAAACAAADSAAAAEqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq",
113
- "anchor": 0.00004167
114
- }
115
- ]
116
- }
@@ -1,264 +0,0 @@
1
- export default class WebAudioFontPlayer {
2
-
3
- #audioCtx = null;
4
- #preset = null;
5
-
6
- #envelopes = [];
7
- #afterTime = 0.05;
8
- #nearZero = 0.000001;
9
-
10
-
11
- constructor(audioCtx, preset) {
12
- this.#audioCtx = audioCtx;
13
- this.#preset = preset;
14
- this.#preset.zones.map(zone => this.#adjustZone(zone));
15
- }
16
-
17
-
18
- queueWaveTable(when, pitch, duration, volume, slides) {
19
- if(this.#audioCtx.state === 'suspended') this.#audioCtx.resume().catch(() => { });
20
-
21
- const vol = this.#limitVolume(volume);
22
- const zone = this.#findZone(pitch);
23
- if (!zone?.buffer) return null;
24
-
25
- const baseDetune = zone.originalPitch - 100.0 * zone.coarseTune - zone.fineTune;
26
- const playbackRate = Math.pow(2, (100.0 * pitch - baseDetune) / 1200.0);
27
- const startWhen = Math.max(when, this.#audioCtx.currentTime);
28
- let waveDuration = duration + this.#afterTime;
29
-
30
- const loop = zone.loopStart >= 1 && zone.loopStart < zone.loopEnd;
31
- if (!loop) waveDuration = Math.min(waveDuration, zone.buffer.duration / playbackRate);
32
-
33
- const envelope = this.#findEnvelope();
34
- this.#setupEnvelope(envelope, zone, vol, startWhen, waveDuration, duration);
35
-
36
- const source = this.#audioCtx.createBufferSource();
37
- source.buffer = zone.buffer;
38
- source.playbackRate.setValueAtTime(playbackRate, 0);
39
-
40
- if (slides?.length > 0) {
41
- source.playbackRate.setValueAtTime(playbackRate, startWhen);
42
- slides.forEach(s => {
43
- const newRate = Math.pow(2, (100.0 * (pitch + s.delta) - baseDetune) / 1200.0);
44
- source.playbackRate.linearRampToValueAtTime(newRate, startWhen + s.when);
45
- });
46
- }
47
-
48
- source.loop = loop;
49
- if (loop) {
50
- const d = zone.delay ?? 0;
51
- source.loopStart = zone.loopStart / zone.sampleRate + d;
52
- source.loopEnd = zone.loopEnd / zone.sampleRate + d;
53
- }
54
-
55
- source.connect(envelope);
56
- source.start(startWhen, zone.delay ?? 0);
57
- source.stop(startWhen + waveDuration);
58
-
59
- envelope.audioBufferSourceNode = source;
60
- envelope.when = startWhen;
61
- envelope.duration = waveDuration;
62
-
63
- return envelope;
64
- }
65
-
66
-
67
- queueChord(prst, w, pchs, d, v, s) {
68
- const vol = this.#limitVolume(v);
69
- return pchs.map((p, i) => this.queueWaveTable(this.#audioCtx, this.#audioCtx.destination, prst, w, p, d, vol - Math.random() * 0.01, s?.[i])).filter(Boolean);
70
- }
71
-
72
-
73
- async cancelQueue() {
74
- this.#envelopes.forEach(e => {
75
- e.gain.cancelScheduledValues(0);
76
- e.gain.setValueAtTime(this.#nearZero, this.#audioCtx.currentTime);
77
- e.when = -1;
78
- try { e.audioBufferSourceNode?.disconnect(); } catch (e) { }
79
- });
80
- }
81
-
82
-
83
- #adjustZone(zone) {
84
- if (zone.buffer) return Promise.resolve(zone);
85
- zone.delay = 0;
86
- if (zone.sample) {
87
- const binaryString = atob(zone.sample);
88
- const len = binaryString.length;
89
- const bytes = new Uint8Array(len);
90
- for (let i = 0; i < len; i++) bytes[i] = binaryString.charCodeAt(i);
91
- const int16Samples = new Int16Array(bytes.buffer);
92
- const numSamples = int16Samples.length;
93
- zone.buffer = this.#audioCtx.createBuffer(1, numSamples, zone.sampleRate);
94
- const float32Array = zone.buffer.getChannelData(0);
95
- for (let i = 0; i < numSamples; i++) float32Array[i] = int16Samples[i] / 32768.0;
96
- this.#applyZoneParameters(zone);
97
- return zone;
98
- } else if (zone.file) {
99
- const decoded = atob(zone.file);
100
- const uint8Array = new Uint8Array(decoded.length);
101
- for (let i = 0; i < decoded.length; i++) uint8Array[i] = decoded.charCodeAt(i);
102
- this.#audioCtx.decodeAudioData(
103
- uint8Array.buffer,
104
- audioBuffer => {
105
- zone.buffer = audioBuffer;
106
- this.#applyZoneParameters(zone);
107
- return zone;
108
- },
109
- error => {
110
- console.error("Audio decoding error:", error);
111
- return false;
112
- }
113
- );
114
- } else {
115
- this.#applyZoneParameters(zone);
116
- return zone;
117
- }
118
- };
119
-
120
-
121
- #applyZoneParameters(zone) {
122
- zone.loopStart = this.#numValue(zone.loopStart, 0);
123
- zone.loopEnd = this.#numValue(zone.loopEnd, 0);
124
- zone.coarseTune = this.#numValue(zone.coarseTune, 0);
125
- zone.fineTune = this.#numValue(zone.fineTune, 0);
126
- zone.originalPitch = this.#numValue(zone.originalPitch, 6000);
127
- zone.sampleRate = this.#numValue(zone.sampleRate, 44100);
128
- };
129
-
130
-
131
- #setupEnvelope(envelope, zone, volume, when, sampleDuration, noteDuration) {
132
- envelope.gain.setValueAtTime(this.#noZeroVolume(0), this.#audioCtx.currentTime);
133
-
134
- const duration = Math.min(noteDuration, sampleDuration - this.#afterTime);
135
- const ahdsr = (zone.ahdsr && zone.ahdsr.length > 0) ? zone.ahdsr : [
136
- { duration: 0, volume: 1 },
137
- { duration: duration, volume: 1 }
138
- ];
139
-
140
- envelope.gain.cancelScheduledValues(when);
141
- const initialVol = (ahdsr[0]?.volume ?? 1) * volume;
142
- envelope.gain.setValueAtTime(this.#noZeroVolume(initialVol), when);
143
-
144
- let lastTime = 0;
145
- let lastVolume = ahdsr[0]?.volume ?? 1;
146
-
147
- for (const stage of ahdsr) {
148
- const { duration: stageDuration, volume: stageVolume } = stage;
149
- if (stageDuration <= 0) continue;
150
- const remainingTime = duration - lastTime;
151
- if (stageDuration > remainingTime) {
152
- const ratio = remainingTime / stageDuration;
153
- const interpolatedVolume = lastVolume + ratio * (stageVolume - lastVolume);
154
- envelope.gain.linearRampToValueAtTime(
155
- this.#noZeroVolume(volume * interpolatedVolume),
156
- when + duration
157
- );
158
- break;
159
- }
160
- lastTime += stageDuration;
161
- lastVolume = stageVolume;
162
- envelope.gain.linearRampToValueAtTime(
163
- this.#noZeroVolume(volume * lastVolume),
164
- when + lastTime
165
- );
166
- }
167
-
168
- envelope.gain.linearRampToValueAtTime(this.#noZeroVolume(0), when + duration + this.#afterTime);
169
- }
170
-
171
-
172
- #findEnvelope() {
173
- let envelope = this.#envelopes.find(e => e.target === this.#audioCtx.destination && this.#audioCtx.currentTime > e.when + e.duration + 0.001);
174
- if (envelope) {
175
- if (envelope.audioBufferSourceNode) {
176
- try {
177
- envelope.audioBufferSourceNode.stop(0);
178
- envelope.audioBufferSourceNode.disconnect();
179
- } catch (e) { }
180
- envelope.audioBufferSourceNode = null;
181
- }
182
- } else {
183
- envelope = this.#audioCtx.createGain();
184
- envelope.gain.value = 0;
185
- envelope.target = this.#audioCtx.destination;
186
- envelope.connect(this.#audioCtx.destination);
187
- envelope.cancel = () => {
188
- if (envelope.when + envelope.duration > this.#audioCtx.currentTime) {
189
- envelope.gain.cancelScheduledValues(0);
190
- envelope.gain.setTargetAtTime(this.#nearZero, this.#audioCtx.currentTime, 0.1);
191
- envelope.when = this.#audioCtx.currentTime + 0.00001;
192
- envelope.duration = 0;
193
- }
194
- };
195
- this.#envelopes.push(envelope);
196
- }
197
- return envelope;
198
- }
199
-
200
-
201
- #findZone(pitch) {
202
- const zone = this.#preset.zones.findLast(z => pitch >= z.keyRangeLow && pitch <= z.keyRangeHigh + 1);
203
- if (zone) this.#adjustZone(zone);
204
- return zone;
205
- };
206
-
207
-
208
- #limitVolume(v) {
209
- const requestedVolume = v ? 1.0 * v : 0.5;
210
- return Math.min(requestedVolume, 0.8);
211
- };
212
-
213
-
214
- #noZeroVolume(n) {
215
- return n > this.#nearZero ? n : this.#nearZero;
216
- }
217
-
218
-
219
- #numValue(a, b) {
220
- return typeof a === "number" ? a : b;
221
- }
222
-
223
- }
224
-
225
-
226
- class WebAudioFontChannel {
227
-
228
- #input = null;
229
- #output = null;
230
- #audioCtx = null;
231
- #limiter = null;
232
-
233
- constructor(audioCtx) {
234
- this.#audioCtx = audioCtx;
235
- this.#input = this.#audioCtx.createGain();
236
-
237
- let lastNode = this.#input;
238
- [32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384].forEach(freq => {
239
- lastNode = this.#bandEqualizer(lastNode, freq);
240
- this[`band${freq < 1000 ? freq : (freq / 1024) + 'k'}`] = lastNode;
241
- });
242
-
243
- this.#limiter = this.#audioCtx.createDynamicsCompressor();
244
- this.#limiter.threshold.setValueAtTime(-3.0, this.#audioCtx.currentTime);
245
- this.#limiter.ratio.setValueAtTime(40, this.#audioCtx.currentTime);
246
- this.#limiter.attack.setValueAtTime(0.000, this.#audioCtx.currentTime);
247
- this.#limiter.release.setValueAtTime(0.25, this.#audioCtx.currentTime);
248
- this.#output = this.#audioCtx.createGain();
249
- lastNode.connect(this.#limiter);
250
- this.#limiter.connect(this.#output);
251
- }
252
-
253
-
254
- #bandEqualizer(from, frequency) {
255
- const filter = this.#audioCtx.createBiquadFilter();
256
- filter.frequency.setTargetAtTime(frequency, 0, 0.0001);
257
- filter.type = "peaking";
258
- filter.gain.setTargetAtTime(0, 0, 0.0001);
259
- filter.Q.setTargetAtTime(1.0, 0, 0.0001);
260
- from.connect(filter);
261
- return filter;
262
- }
263
-
264
- }