@atmosx/event-product-parser 2.0.16 → 3.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/README.md +248 -187
- package/dist/cjs/index.cjs +12218 -3139
- package/dist/esm/index.mjs +12401 -3327
- package/dist/index.d.mts +235 -0
- package/dist/index.d.ts +235 -0
- package/package.json +6 -4
- package/src/@building/building.clean.ts +30 -0
- package/src/@building/building.create.ts +42 -0
- package/src/@building/building.enhance.ts +56 -0
- package/src/@building/building.geometry.ts +48 -0
- package/src/@building/building.headers.ts +37 -0
- package/src/@building/building.office.ts +43 -0
- package/src/@building/building.polygon.ts +71 -0
- package/src/@building/building.properties.ts +89 -0
- package/src/@building/building.signature.ts +61 -0
- package/src/@building/building.tags.ts +24 -0
- package/src/@building/building.tracking.ts +68 -0
- package/src/@building/building.validate.ts +147 -0
- package/src/@core/core.getEvents.ts +25 -0
- package/src/@core/core.getNodes.ts +25 -0
- package/src/@core/core.getRandomEvent.ts +25 -0
- package/src/@core/core.getVersion.ts +25 -0
- package/src/@core/core.listener.ts +24 -0
- package/src/@core/core.setNode.ts +81 -0
- package/src/@core/core.start.ts +59 -0
- package/src/@core/core.stop.ts +32 -0
- package/src/@dictionaries/dictionaries.betterEventNames.ts +89 -0
- package/src/@dictionaries/dictionaries.eventActions.ts +28 -0
- package/src/@dictionaries/{awips.ts → dictionaries.eventAwipAbreviations.ts} +13 -7
- package/src/@dictionaries/dictionaries.eventCancelMessages.ts +30 -0
- package/src/@dictionaries/dictionaries.eventCauses.ts +36 -0
- package/src/@dictionaries/dictionaries.eventProducts.ts +25 -0
- package/src/@dictionaries/dictionaries.eventRecords.ts +25 -0
- package/src/@dictionaries/dictionaries.eventSeverity.ts +27 -0
- package/src/@dictionaries/dictionaries.eventStatus.ts +31 -0
- package/src/@dictionaries/{signatures.ts → dictionaries.eventTags.ts} +13 -68
- package/src/@dictionaries/dictionaries.eventTypes.ts +82 -0
- package/src/@dictionaries/dictionaries.eventsOffshore.ts +31 -0
- package/src/@dictionaries/dictionaries.hailStrings.ts +33 -0
- package/src/@dictionaries/{icao.ts → dictionaries.officeICAOs.ts} +13 -6
- package/src/@dictionaries/dictionaries.regExp.ts +28 -0
- package/src/@dictionaries/dictionaries.shapefileLinks.ts +36 -0
- package/src/@dictionaries/dictionaries.statusCorrelationText.ts +40 -0
- package/src/@dictionaries/dictionaries.testSignatures.ts +24 -0
- package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +68 -0
- package/src/@events/events.api.ts +113 -0
- package/src/@events/events.text.ts +79 -0
- package/src/@events/events.ugc.ts +83 -0
- package/src/@events/events.vtec.ts +87 -0
- package/src/@manager/manager.mkEvent.ts +95 -0
- package/src/@manager/manager.rmEvent.ts +46 -0
- package/src/@manager/manager.setHash.ts +37 -0
- package/src/@manager/manager.updateNodes.ts +55 -0
- package/src/@manager/manager.updateWebhooks.ts +50 -0
- package/src/@modules/@database/database.cache.ts +48 -0
- package/src/@modules/@database/database.init.ts +45 -0
- package/src/@modules/@database/database.shapefiles.ts +96 -0
- package/src/@modules/@database/database.stanza.ts +48 -0
- package/src/@modules/@eas/eas.getFloatPCM16.ts +29 -0
- package/src/@modules/@eas/eas.getMergedPCM16.ts +32 -0
- package/src/@modules/@eas/eas.getPCM16.ts +52 -0
- package/src/@modules/@eas/eas.getPCMToFloat.ts +26 -0
- package/src/@modules/@eas/eas.getSampledPCM16.ts +36 -0
- package/src/@modules/@eas/eas.getWavPCM16.ts +52 -0
- package/src/@modules/@eas/eas.setAFSK.ts +52 -0
- package/src/@modules/@eas/eas.setAsciiToBits.ts +32 -0
- package/src/@modules/@eas/eas.setAttentionTone.ts +40 -0
- package/src/@modules/@eas/eas.setEasTone.ts +137 -0
- package/src/@modules/@eas/eas.setNoise.ts +31 -0
- package/src/@modules/@eas/eas.setRadioEffect.ts +49 -0
- package/src/@modules/@eas/eas.setSameHeader.ts +45 -0
- package/src/@modules/@stanza/stanza.getAwipsType.ts +46 -0
- package/src/@modules/@stanza/stanza.validate.ts +50 -0
- package/src/@modules/@utilities/utilities.createHttp.ts +85 -0
- package/src/@modules/@utilities/utilities.createWebhook.ts +100 -0
- package/src/@modules/@utilities/utilities.getFormattedTime.ts +43 -0
- package/src/@modules/@utilities/utilities.getSettings.ts +25 -0
- package/src/@modules/@utilities/utilities.getShapeNearestPoint.ts +114 -0
- package/src/@modules/@utilities/utilities.setCronSchedule.ts +65 -0
- package/src/@modules/@utilities/utilities.setEventEmit.ts +41 -0
- package/src/@modules/@utilities/utilities.setListener.ts +30 -0
- package/src/@modules/@utilities/utilities.setSettings.ts +42 -0
- package/src/@modules/@utilities/utilities.setSleep.ts +33 -0
- package/src/@modules/@utilities/utilities.setTimeoutAction.ts +59 -0
- package/src/@modules/@utilities/utilities.setWarning.ts +34 -0
- package/src/@modules/@xmpp/xmpp.xDeploy.ts +58 -0
- package/src/@modules/@xmpp/xmpp.xError.ts +29 -0
- package/src/@modules/@xmpp/xmpp.xOffline.ts +38 -0
- package/src/@modules/@xmpp/xmpp.xOnline.ts +45 -0
- package/src/@modules/@xmpp/xmpp.xReconnect.ts +64 -0
- package/src/@modules/@xmpp/xmpp.xStanza.ts +63 -0
- package/src/@parsers/@hvtec/hvtec.extract.ts +40 -0
- package/src/@parsers/@pvtec/pvtec.expires.ts +26 -0
- package/src/@parsers/@pvtec/pvtec.extract.ts +49 -0
- package/src/@parsers/@text/text.getDescriptionFromProduct.ts +53 -0
- package/src/@parsers/@text/text.getPolygonFromProduct.ts +32 -0
- package/src/@parsers/@text/text.getTextFromProduct.ts +43 -0
- package/src/@parsers/@text/text.getXML.ts +61 -0
- package/src/@parsers/@ugc/ugc.coordinates.ts +110 -0
- package/src/@parsers/@ugc/ugc.expiry.ts +32 -0
- package/src/@parsers/@ugc/ugc.extract.ts +37 -0
- package/src/@parsers/@ugc/ugc.header.ts +30 -0
- package/src/@parsers/@ugc/ugc.locations.ts +29 -0
- package/src/@parsers/@ugc/ugc.zones.ts +52 -0
- package/src/@types/type.event.ts +67 -0
- package/src/@types/type.properties.ts +75 -0
- package/src/@types/types.attributes.ts +28 -0
- package/src/@types/types.compiled.ts +35 -0
- package/src/@types/types.hash.ts +24 -0
- package/src/@types/types.hvtec.ts +25 -0
- package/src/@types/types.pvtec.ts +30 -0
- package/src/@types/types.settings.ts +76 -0
- package/src/@types/types.stanza.ts +37 -0
- package/src/@types/types.ugc.ts +24 -0
- package/src/@types/types.webhook.ts +26 -0
- package/src/bootstrap.ts +85 -163
- package/src/index.ts +47 -216
- package/test.js +78 -51
- package/tsup.config.ts +1 -0
- package/src/@dictionaries/events.ts +0 -168
- package/src/@parsers/@events/api.ts +0 -146
- package/src/@parsers/@events/cap.ts +0 -123
- package/src/@parsers/@events/text.ts +0 -104
- package/src/@parsers/@events/ugc.ts +0 -107
- package/src/@parsers/@events/vtec.ts +0 -76
- package/src/@parsers/events.ts +0 -392
- package/src/@parsers/hvtec.ts +0 -46
- package/src/@parsers/pvtec.ts +0 -72
- package/src/@parsers/stanza.ts +0 -97
- package/src/@parsers/text.ts +0 -165
- package/src/@parsers/ugc.ts +0 -247
- package/src/@submodules/database.ts +0 -201
- package/src/@submodules/eas.ts +0 -490
- package/src/@submodules/utils.ts +0 -191
- package/src/@submodules/xmpp.ts +0 -142
- package/src/types.ts +0 -259
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
import { bootstrap } from '../../bootstrap'
|
|
22
|
+
import { setWarning } from '../@utilities/utilities.setWarning';
|
|
23
|
+
import { TypeSettings } from "../../@types/types.settings"
|
|
24
|
+
import { TypeStanzaCompiled } from '../../@types/types.compiled';
|
|
25
|
+
|
|
26
|
+
export const importStanza = async (stanza: TypeStanzaCompiled): Promise<void> => {
|
|
27
|
+
const settings = bootstrap.settings as TypeSettings;
|
|
28
|
+
try {
|
|
29
|
+
if (!settings.NOAAWeatherWireServiceSettings.CacheSettings.Enabled) { return }
|
|
30
|
+
bootstrap.database
|
|
31
|
+
.prepare(`INSERT OR IGNORE INTO stanzas (type, stanza, issued) VALUES (?, ?, ?)`)
|
|
32
|
+
.run(stanza.getType.type, JSON.stringify(stanza), stanza.attributes.issue)
|
|
33
|
+
const count = bootstrap.database
|
|
34
|
+
.prepare(`SELECT COUNT(*) as total FROM stanzas`)
|
|
35
|
+
.get() as { total: number }
|
|
36
|
+
const max = settings.NOAAWeatherWireServiceSettings.CacheSettings.MaxDatabaseHistory;
|
|
37
|
+
if (count.total > max) {
|
|
38
|
+
const toDelete = count.total - max;
|
|
39
|
+
if (toDelete > 0) {
|
|
40
|
+
bootstrap.database
|
|
41
|
+
.prepare(`DELETE FROM stanzas WHERE id IN (SELECT id FROM stanzas ORDER BY issued ASC LIMIT ?)`)
|
|
42
|
+
.run(toDelete);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
} catch (error) {
|
|
46
|
+
setWarning({ message: `An error occurred while importing stanza: ${error.message}` })
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export const getFloatPCM16 = (float32: Float32Array): Int16Array => {
|
|
22
|
+
const out = new Int16Array(float32.length);
|
|
23
|
+
for (let i = 0; i < float32.length; i++) {
|
|
24
|
+
let v = Math.max(-1, Math.min(1, float32[i]));
|
|
25
|
+
out[i] = Math.round(v * 32767);
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export const getMergedPCM16 = (arrays: Int16Array[]): Int16Array => {
|
|
22
|
+
let total = 0;
|
|
23
|
+
for (const a of arrays) total += a.length;
|
|
24
|
+
const out = new Int16Array(total);
|
|
25
|
+
let o = 0;
|
|
26
|
+
for (const a of arrays) {
|
|
27
|
+
out.set(a, o);
|
|
28
|
+
o += a.length;
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export const getPCM16 = (samples: Record<string, number>[], sampleRate: number): Buffer => {
|
|
22
|
+
let o = 0;
|
|
23
|
+
const bytesPerSample = 2;
|
|
24
|
+
const blockAlign = 1 * bytesPerSample;
|
|
25
|
+
const byteRate = sampleRate * blockAlign;
|
|
26
|
+
const subchunk2Size = samples.length * bytesPerSample;
|
|
27
|
+
const chunkSize = 36 + subchunk2Size;
|
|
28
|
+
const buffer = Buffer.alloc(44 + subchunk2Size);
|
|
29
|
+
|
|
30
|
+
buffer.write("RIFF", o); o += 4;
|
|
31
|
+
buffer.writeUInt32LE(chunkSize, o); o += 4;
|
|
32
|
+
buffer.write("WAVE", o); o += 4;
|
|
33
|
+
|
|
34
|
+
buffer.write("fmt ", o); o += 4;
|
|
35
|
+
buffer.writeUInt32LE(16, o); o += 4;
|
|
36
|
+
buffer.writeUInt16LE(1, o); o += 2;
|
|
37
|
+
buffer.writeUInt16LE(1, o); o += 2;
|
|
38
|
+
buffer.writeUInt32LE(sampleRate, o); o += 4;
|
|
39
|
+
buffer.writeUInt32LE(byteRate, o); o += 4;
|
|
40
|
+
buffer.writeUInt16LE(blockAlign, o); o += 2;
|
|
41
|
+
buffer.writeUInt16LE(16, o); o += 2;
|
|
42
|
+
|
|
43
|
+
buffer.write("data", o); o += 4;
|
|
44
|
+
buffer.writeUInt32LE(subchunk2Size, o); o += 4;
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < samples.length; i++, o += 2) {
|
|
47
|
+
buffer.writeInt16LE(samples[i].value, o);
|
|
48
|
+
}
|
|
49
|
+
return buffer;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export const getPCMToFloat = (int16: Int16Array): Float32Array => {
|
|
22
|
+
const out = new Float32Array(int16.length);
|
|
23
|
+
for (let i = 0; i < int16.length; i++) out[i] = int16[i] / 32768;
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export const getSampledPCM16 = (int16: Int16Array, originalRate: number, targetRate: number): Int16Array => {
|
|
22
|
+
if (originalRate === targetRate) return int16;
|
|
23
|
+
const ratio = targetRate / originalRate;
|
|
24
|
+
const outLen = Math.max(1, Math.round(int16.length * ratio));
|
|
25
|
+
const out = new Int16Array(outLen);
|
|
26
|
+
for (let i = 0; i < outLen; i++) {
|
|
27
|
+
const pos = i / ratio;
|
|
28
|
+
const i0 = Math.floor(pos);
|
|
29
|
+
const i1 = Math.min(i0 + 1, int16.length - 1);
|
|
30
|
+
const frac = pos - i0;
|
|
31
|
+
const v = int16[i0] * (1 - frac) + int16[i1] * frac;
|
|
32
|
+
out[i] = Math.round(v);
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
interface getWavPCM16Response {
|
|
22
|
+
samples: Int16Array
|
|
23
|
+
sampleRate: number
|
|
24
|
+
channels: number
|
|
25
|
+
bitsPerSample: number
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const getWavPCM16 = (buffer: Buffer): getWavPCM16Response => {
|
|
29
|
+
if (buffer.toString("ascii", 0, 4) !== "RIFF" || buffer.toString("ascii", 8, 12) !== "WAVE") { return null; }
|
|
30
|
+
let fmt = null;
|
|
31
|
+
let data = null;
|
|
32
|
+
let i = 12;
|
|
33
|
+
while (i + 8 <= buffer.length) {
|
|
34
|
+
const id = buffer.toString("ascii", i, i + 4);
|
|
35
|
+
const size = buffer.readUInt32LE(i + 4);
|
|
36
|
+
const start = i + 8;
|
|
37
|
+
const end = start + size;
|
|
38
|
+
if (id === "fmt ") fmt = buffer.slice(start, end);
|
|
39
|
+
if (id === "data") data = buffer.slice(start, end);
|
|
40
|
+
i = end + (size % 2);
|
|
41
|
+
}
|
|
42
|
+
if (!fmt || !data) return null;
|
|
43
|
+
const audioFormat = fmt.readUInt16LE(0);
|
|
44
|
+
const channels = fmt.readUInt16LE(2);
|
|
45
|
+
const sampleRate = fmt.readUInt32LE(4);
|
|
46
|
+
const bitsPerSample = fmt.readUInt16LE(14);
|
|
47
|
+
if (audioFormat !== 1 || bitsPerSample !== 16 || channels !== 1) { return null; }
|
|
48
|
+
const samples = new Int16Array(data.buffer, data.byteOffset, data.length / 2);
|
|
49
|
+
return { samples: new Int16Array(samples), sampleRate, channels, bitsPerSample };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
export const setAFSK = (bits: number[], sampleRate: number): Int16Array => {
|
|
23
|
+
const baud = 520.83;
|
|
24
|
+
const markFreq = 2083.3;
|
|
25
|
+
const spaceFreq = 1562.5;
|
|
26
|
+
const amplitude = 0.6;
|
|
27
|
+
const twoPi = Math.PI * 2;
|
|
28
|
+
const result = [];
|
|
29
|
+
let phase = 0;
|
|
30
|
+
let frac = 0;
|
|
31
|
+
for (let b = 0; b < bits.length; b++) {
|
|
32
|
+
const bit = bits[b];
|
|
33
|
+
const freq = bit ? markFreq : spaceFreq;
|
|
34
|
+
const samplesPerBit = sampleRate / baud + frac;
|
|
35
|
+
const n = Math.round(samplesPerBit);
|
|
36
|
+
frac = samplesPerBit - n;
|
|
37
|
+
const inc = twoPi * freq / sampleRate;
|
|
38
|
+
for (let i = 0; i < n; i++) {
|
|
39
|
+
result.push(Math.round(Math.sin(phase) * amplitude * 32767));
|
|
40
|
+
phase += inc;
|
|
41
|
+
if (phase > twoPi) phase -= twoPi;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const fadeSamples = Math.floor(sampleRate * 0.002);
|
|
45
|
+
for (let i = 0; i < fadeSamples; i++) {
|
|
46
|
+
const gain = i / fadeSamples;
|
|
47
|
+
result[i] = Math.round(result[i] * gain);
|
|
48
|
+
result[result.length - 1 - i] = Math.round(result[result.length - 1 - i] * gain);
|
|
49
|
+
}
|
|
50
|
+
return Int16Array.from(result);
|
|
51
|
+
}
|
|
52
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
export const setAsciiToBits = (str: string): number[] => {
|
|
23
|
+
const bits = [];
|
|
24
|
+
for (let i = 0; i < str.length; i++) {
|
|
25
|
+
const c = str.charCodeAt(i) & 0xFF;
|
|
26
|
+
bits.push(0);
|
|
27
|
+
for (let b = 0; b < 8; b++) bits.push((c >> b) & 1);
|
|
28
|
+
bits.push(1, 1);
|
|
29
|
+
}
|
|
30
|
+
return bits;
|
|
31
|
+
}
|
|
32
|
+
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export const setAttentionTone = (ms: number, sampleRate: number): Int16Array => {
|
|
22
|
+
const len = Math.floor(ms * sampleRate);
|
|
23
|
+
const out = new Int16Array(len);
|
|
24
|
+
const f1 = 853;
|
|
25
|
+
const f2 = 960;
|
|
26
|
+
const twoPi = Math.PI * 2;
|
|
27
|
+
const amp = 0.1;
|
|
28
|
+
const fadeLen = Math.floor(sampleRate * 0.00);
|
|
29
|
+
for (let i = 0; i < len; i++) {
|
|
30
|
+
const t = i / sampleRate;
|
|
31
|
+
const s = Math.sin(twoPi * f1 * t) + Math.sin(twoPi * f2 * t);
|
|
32
|
+
let gain = 1;
|
|
33
|
+
if (i < fadeLen) gain = i / fadeLen;
|
|
34
|
+
else if (i > len - fadeLen) gain = (len - i) / fadeLen;
|
|
35
|
+
const v = Math.max(-1, Math.min(1, (s / 2) * amp * gain));
|
|
36
|
+
out[i] = Math.round(v * 32767);
|
|
37
|
+
}
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { TypeSettings } from "../../@types/types.settings";
|
|
21
|
+
import { transcribedMessageReplacements } from "../../@dictionaries/dictionaries.transcribedMessageReplacements";
|
|
22
|
+
import { bootstrap } from "../../bootstrap";
|
|
23
|
+
import { setSleep } from "../@utilities/utilities.setSleep"
|
|
24
|
+
import { getWavPCM16 } from "./eas.getWavPCM16";
|
|
25
|
+
import { getSampledPCM16 } from "./eas.getSampledPCM16";
|
|
26
|
+
import { setRadioEffect } from "./eas.setRadioEffect";
|
|
27
|
+
import { setSameHeader } from "./eas.setSameHeader";
|
|
28
|
+
import { setAttentionTone } from "./eas.setAttentionTone";
|
|
29
|
+
import { getMergedPCM16 } from "./eas.getMergedPCM16";
|
|
30
|
+
import { setNoise } from "./eas.setNoise";
|
|
31
|
+
import { getPCM16 } from "./eas.getPCM16";
|
|
32
|
+
import { join } from 'path'
|
|
33
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'fs'
|
|
34
|
+
import { execSync } from 'child_process'
|
|
35
|
+
import { platform } from 'os'
|
|
36
|
+
import { setWarning } from "../@utilities/utilities.setWarning";
|
|
37
|
+
import say from 'say'
|
|
38
|
+
|
|
39
|
+
interface GenerateEASOptions {
|
|
40
|
+
message: string
|
|
41
|
+
header: string
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const setEasTone = async (options: GenerateEASOptions): Promise<string> => {
|
|
45
|
+
const settings = bootstrap.settings as TypeSettings;
|
|
46
|
+
const directory = settings.GlobalSettings.EASSettings.ArchiveDirectory;
|
|
47
|
+
const prefix = settings.GlobalSettings.EASSettings.IntroWavFile;
|
|
48
|
+
let message = options.message;
|
|
49
|
+
let header = options.header;
|
|
50
|
+
let buffTTS: Buffer;
|
|
51
|
+
let buffRadio: any;
|
|
52
|
+
let buffFull: any[] = [];
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
const tmpTTS = join(directory, `/temp/${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, '')}.wav`)
|
|
56
|
+
const outTTS = join(directory, `/output/${Math.random().toString(36).substring(2, 15)}-${header.replace(/[^a-zA-Z0-9]/g, '')}.wav`)
|
|
57
|
+
const vTTS = process.platform === `win32` ? `Microsoft David Desktop` : `en-US-GuyNerual`;
|
|
58
|
+
const vPlatform = platform();
|
|
59
|
+
|
|
60
|
+
if (!existsSync(directory)) {
|
|
61
|
+
mkdirSync(directory, { recursive: true });
|
|
62
|
+
}
|
|
63
|
+
if (!existsSync(join(directory, `/temp`))) {
|
|
64
|
+
mkdirSync(join(directory, `/temp`), { recursive: true });
|
|
65
|
+
}
|
|
66
|
+
if (!existsSync(join(directory, `/output`))) {
|
|
67
|
+
mkdirSync(join(directory, `/output`), { recursive: true });
|
|
68
|
+
}
|
|
69
|
+
for (const {regex, replacement} of transcribedMessageReplacements) {
|
|
70
|
+
message = message.replace(regex, replacement)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (vPlatform != `win32`) {
|
|
74
|
+
setWarning({
|
|
75
|
+
title: `EAS`,
|
|
76
|
+
message: `Generation isn't supported with this OS. Please wait for further updates before trying again`
|
|
77
|
+
})
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
say.export(message, vTTS, 1.0, tmpTTS)
|
|
82
|
+
while (!existsSync(tmpTTS) || (buffTTS = readFileSync(tmpTTS)).length == 0) {
|
|
83
|
+
await setSleep({timeout: 25});
|
|
84
|
+
}
|
|
85
|
+
const vWav = getWavPCM16(buffTTS);
|
|
86
|
+
const vSamples = getSampledPCM16(vWav.samples, vWav.sampleRate, 8000)
|
|
87
|
+
const vRadio = setRadioEffect(vSamples, 8000)
|
|
88
|
+
|
|
89
|
+
if (existsSync(prefix)) {
|
|
90
|
+
let tBuffer = readFileSync(prefix);
|
|
91
|
+
let tWav = getWavPCM16(tBuffer);
|
|
92
|
+
|
|
93
|
+
if (tWav == null) {
|
|
94
|
+
try {
|
|
95
|
+
const converted = join(directory, `/temp/${Math.random().toString(36).substring(2, 15)}.converted.wav`)
|
|
96
|
+
execSync(`ffmpeg -y -i "${prefix}" -ar 8000 -ac 1 -sample_fmt s16 "${converted}"`, { stdio: 'ignore' })
|
|
97
|
+
if (existsSync(converted)) {
|
|
98
|
+
tBuffer = readFileSync(converted)
|
|
99
|
+
tWav = getWavPCM16(tBuffer)
|
|
100
|
+
try { unlinkSync(converted) } catch {}
|
|
101
|
+
}
|
|
102
|
+
} catch (e) {}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (tWav == null) {
|
|
106
|
+
setWarning({ title: `EAS`, message: `Intro tone isn't a valid .WAV file or isn't in PCM 16-bit format. Converted attempt failed; please convert it then try again.` })
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const tSamples = (tWav.sampleRate != 8000 ? getSampledPCM16(tWav.samples, tWav.sampleRate, 8000) : tWav.samples)
|
|
111
|
+
buffRadio = setRadioEffect(tSamples, 8000)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
buffFull = buffRadio != null ? [buffRadio, new Int16Array(Math.floor(0.5 * 8000))] : [];
|
|
115
|
+
buffFull.push(
|
|
116
|
+
setSameHeader(header, 3, 8000, {
|
|
117
|
+
preMarkSec: 1.1,
|
|
118
|
+
gapSec: 0.5,
|
|
119
|
+
}),
|
|
120
|
+
new Int16Array(Math.floor(0.5 * 8000)),
|
|
121
|
+
setAttentionTone(8, 8000),
|
|
122
|
+
new Int16Array(Math.floor(0.5 * 8000)),
|
|
123
|
+
vRadio
|
|
124
|
+
)
|
|
125
|
+
for (let i = 0; i < 3; i++) {
|
|
126
|
+
buffFull.push(setSameHeader(header, 1, 8000, { preMarkSec: 0.5, gapSec: 0.1 }))
|
|
127
|
+
buffFull.push(new Int16Array(Math.floor(0.5 * 8000)));
|
|
128
|
+
}
|
|
129
|
+
const aSamples = getMergedPCM16(buffFull);
|
|
130
|
+
const aFinal = setNoise(aSamples, 0.002);
|
|
131
|
+
const aBuffer = getPCM16(Array.from(aFinal).map(v => ({ value: v })), 8000);
|
|
132
|
+
writeFileSync(outTTS, aBuffer)
|
|
133
|
+
try{unlinkSync(tmpTTS)} catch {}
|
|
134
|
+
return outTTS;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
import { getPCMToFloat } from "./eas.getPCMToFloat";
|
|
21
|
+
import { getFloatPCM16 } from "./eas.getFloatPCM16";
|
|
22
|
+
|
|
23
|
+
export const setNoise = (int16: Int16Array, noiseLevel: number = 0.02): Int16Array => {
|
|
24
|
+
const x = getPCMToFloat(int16);
|
|
25
|
+
for (let i = 0; i < x.length; i++) x[i] += (Math.random() * 2 - 1) * noiseLevel;
|
|
26
|
+
let peak = 0;
|
|
27
|
+
for (let i = 0; i < x.length; i++) peak = Math.max(peak, Math.abs(x[i]));
|
|
28
|
+
if (peak > 1) for (let i = 0; i < x.length; i++) x[i] *= 0.98 / peak;
|
|
29
|
+
return getFloatPCM16(x);
|
|
30
|
+
}
|
|
31
|
+
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/*
|
|
2
|
+
_ _ _ __ __
|
|
3
|
+
/\ | | | | (_) \ \ / /
|
|
4
|
+
/ \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
|
|
5
|
+
/ /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
|
|
6
|
+
/ ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
|
|
7
|
+
/_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
|
|
8
|
+
| |
|
|
9
|
+
|_|
|
|
10
|
+
|
|
11
|
+
Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
|
|
12
|
+
Discord: https://atmosphericx-discord.scriptkitty.cafe
|
|
13
|
+
Ko-Fi: https://ko-fi.com/k3yomi
|
|
14
|
+
Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
|
|
15
|
+
|
|
16
|
+
Internal Package: @atmosx/event-product-parser
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
*/
|
|
20
|
+
import { getPCMToFloat } from "./eas.getPCMToFloat";
|
|
21
|
+
import { getFloatPCM16 } from "./eas.getFloatPCM16";
|
|
22
|
+
|
|
23
|
+
export const setRadioEffect = (int16: Int16Array, sampleRate: number): Int16Array => {
|
|
24
|
+
const hpCut = 3555;
|
|
25
|
+
const lpCut = 1600;
|
|
26
|
+
const x = getPCMToFloat(int16);
|
|
27
|
+
const dt = 1 / sampleRate;
|
|
28
|
+
const rcHP = 1 / (2 * Math.PI * hpCut);
|
|
29
|
+
const aHP = rcHP / (rcHP + dt);
|
|
30
|
+
let yHP = 0, xPrev = 0;
|
|
31
|
+
for (let i = 0; i < x.length; i++) {
|
|
32
|
+
const xi = x[i];
|
|
33
|
+
yHP = aHP * (yHP + xi - xPrev);
|
|
34
|
+
xPrev = xi;
|
|
35
|
+
x[i] = yHP;
|
|
36
|
+
}
|
|
37
|
+
const rcLP = 1 / (2 * Math.PI * lpCut);
|
|
38
|
+
const aLP = dt / (rcLP + dt);
|
|
39
|
+
let yLP = 0;
|
|
40
|
+
for (let i = 0; i < x.length; i++) {
|
|
41
|
+
yLP = yLP + aLP * (x[i] - yLP);
|
|
42
|
+
x[i] = yLP;
|
|
43
|
+
}
|
|
44
|
+
const compGain = 2.0;
|
|
45
|
+
const norm = Math.tanh(compGain);
|
|
46
|
+
for (let i = 0; i < x.length; i++) x[i] = Math.tanh(x[i] * compGain) / norm;
|
|
47
|
+
return getFloatPCM16(x);
|
|
48
|
+
}
|
|
49
|
+
|