@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.
Files changed (136) hide show
  1. package/README.md +248 -187
  2. package/dist/cjs/index.cjs +12218 -3139
  3. package/dist/esm/index.mjs +12401 -3327
  4. package/dist/index.d.mts +235 -0
  5. package/dist/index.d.ts +235 -0
  6. package/package.json +6 -4
  7. package/src/@building/building.clean.ts +30 -0
  8. package/src/@building/building.create.ts +42 -0
  9. package/src/@building/building.enhance.ts +56 -0
  10. package/src/@building/building.geometry.ts +48 -0
  11. package/src/@building/building.headers.ts +37 -0
  12. package/src/@building/building.office.ts +43 -0
  13. package/src/@building/building.polygon.ts +71 -0
  14. package/src/@building/building.properties.ts +89 -0
  15. package/src/@building/building.signature.ts +61 -0
  16. package/src/@building/building.tags.ts +24 -0
  17. package/src/@building/building.tracking.ts +68 -0
  18. package/src/@building/building.validate.ts +147 -0
  19. package/src/@core/core.getEvents.ts +25 -0
  20. package/src/@core/core.getNodes.ts +25 -0
  21. package/src/@core/core.getRandomEvent.ts +25 -0
  22. package/src/@core/core.getVersion.ts +25 -0
  23. package/src/@core/core.listener.ts +24 -0
  24. package/src/@core/core.setNode.ts +81 -0
  25. package/src/@core/core.start.ts +59 -0
  26. package/src/@core/core.stop.ts +32 -0
  27. package/src/@dictionaries/dictionaries.betterEventNames.ts +89 -0
  28. package/src/@dictionaries/dictionaries.eventActions.ts +28 -0
  29. package/src/@dictionaries/{awips.ts → dictionaries.eventAwipAbreviations.ts} +13 -7
  30. package/src/@dictionaries/dictionaries.eventCancelMessages.ts +30 -0
  31. package/src/@dictionaries/dictionaries.eventCauses.ts +36 -0
  32. package/src/@dictionaries/dictionaries.eventProducts.ts +25 -0
  33. package/src/@dictionaries/dictionaries.eventRecords.ts +25 -0
  34. package/src/@dictionaries/dictionaries.eventSeverity.ts +27 -0
  35. package/src/@dictionaries/dictionaries.eventStatus.ts +31 -0
  36. package/src/@dictionaries/{signatures.ts → dictionaries.eventTags.ts} +13 -68
  37. package/src/@dictionaries/dictionaries.eventTypes.ts +82 -0
  38. package/src/@dictionaries/dictionaries.eventsOffshore.ts +31 -0
  39. package/src/@dictionaries/dictionaries.hailStrings.ts +33 -0
  40. package/src/@dictionaries/{icao.ts → dictionaries.officeICAOs.ts} +13 -6
  41. package/src/@dictionaries/dictionaries.regExp.ts +28 -0
  42. package/src/@dictionaries/dictionaries.shapefileLinks.ts +36 -0
  43. package/src/@dictionaries/dictionaries.statusCorrelationText.ts +40 -0
  44. package/src/@dictionaries/dictionaries.testSignatures.ts +24 -0
  45. package/src/@dictionaries/dictionaries.transcribedMessageReplacements.ts +68 -0
  46. package/src/@events/events.api.ts +113 -0
  47. package/src/@events/events.text.ts +79 -0
  48. package/src/@events/events.ugc.ts +83 -0
  49. package/src/@events/events.vtec.ts +87 -0
  50. package/src/@manager/manager.mkEvent.ts +95 -0
  51. package/src/@manager/manager.rmEvent.ts +46 -0
  52. package/src/@manager/manager.setHash.ts +37 -0
  53. package/src/@manager/manager.updateNodes.ts +55 -0
  54. package/src/@manager/manager.updateWebhooks.ts +50 -0
  55. package/src/@modules/@database/database.cache.ts +48 -0
  56. package/src/@modules/@database/database.init.ts +45 -0
  57. package/src/@modules/@database/database.shapefiles.ts +96 -0
  58. package/src/@modules/@database/database.stanza.ts +48 -0
  59. package/src/@modules/@eas/eas.getFloatPCM16.ts +29 -0
  60. package/src/@modules/@eas/eas.getMergedPCM16.ts +32 -0
  61. package/src/@modules/@eas/eas.getPCM16.ts +52 -0
  62. package/src/@modules/@eas/eas.getPCMToFloat.ts +26 -0
  63. package/src/@modules/@eas/eas.getSampledPCM16.ts +36 -0
  64. package/src/@modules/@eas/eas.getWavPCM16.ts +52 -0
  65. package/src/@modules/@eas/eas.setAFSK.ts +52 -0
  66. package/src/@modules/@eas/eas.setAsciiToBits.ts +32 -0
  67. package/src/@modules/@eas/eas.setAttentionTone.ts +40 -0
  68. package/src/@modules/@eas/eas.setEasTone.ts +137 -0
  69. package/src/@modules/@eas/eas.setNoise.ts +31 -0
  70. package/src/@modules/@eas/eas.setRadioEffect.ts +49 -0
  71. package/src/@modules/@eas/eas.setSameHeader.ts +45 -0
  72. package/src/@modules/@stanza/stanza.getAwipsType.ts +46 -0
  73. package/src/@modules/@stanza/stanza.validate.ts +50 -0
  74. package/src/@modules/@utilities/utilities.createHttp.ts +85 -0
  75. package/src/@modules/@utilities/utilities.createWebhook.ts +100 -0
  76. package/src/@modules/@utilities/utilities.getFormattedTime.ts +43 -0
  77. package/src/@modules/@utilities/utilities.getSettings.ts +25 -0
  78. package/src/@modules/@utilities/utilities.getShapeNearestPoint.ts +114 -0
  79. package/src/@modules/@utilities/utilities.setCronSchedule.ts +65 -0
  80. package/src/@modules/@utilities/utilities.setEventEmit.ts +41 -0
  81. package/src/@modules/@utilities/utilities.setListener.ts +30 -0
  82. package/src/@modules/@utilities/utilities.setSettings.ts +42 -0
  83. package/src/@modules/@utilities/utilities.setSleep.ts +33 -0
  84. package/src/@modules/@utilities/utilities.setTimeoutAction.ts +59 -0
  85. package/src/@modules/@utilities/utilities.setWarning.ts +34 -0
  86. package/src/@modules/@xmpp/xmpp.xDeploy.ts +58 -0
  87. package/src/@modules/@xmpp/xmpp.xError.ts +29 -0
  88. package/src/@modules/@xmpp/xmpp.xOffline.ts +38 -0
  89. package/src/@modules/@xmpp/xmpp.xOnline.ts +45 -0
  90. package/src/@modules/@xmpp/xmpp.xReconnect.ts +64 -0
  91. package/src/@modules/@xmpp/xmpp.xStanza.ts +63 -0
  92. package/src/@parsers/@hvtec/hvtec.extract.ts +40 -0
  93. package/src/@parsers/@pvtec/pvtec.expires.ts +26 -0
  94. package/src/@parsers/@pvtec/pvtec.extract.ts +49 -0
  95. package/src/@parsers/@text/text.getDescriptionFromProduct.ts +53 -0
  96. package/src/@parsers/@text/text.getPolygonFromProduct.ts +32 -0
  97. package/src/@parsers/@text/text.getTextFromProduct.ts +43 -0
  98. package/src/@parsers/@text/text.getXML.ts +61 -0
  99. package/src/@parsers/@ugc/ugc.coordinates.ts +110 -0
  100. package/src/@parsers/@ugc/ugc.expiry.ts +32 -0
  101. package/src/@parsers/@ugc/ugc.extract.ts +37 -0
  102. package/src/@parsers/@ugc/ugc.header.ts +30 -0
  103. package/src/@parsers/@ugc/ugc.locations.ts +29 -0
  104. package/src/@parsers/@ugc/ugc.zones.ts +52 -0
  105. package/src/@types/type.event.ts +67 -0
  106. package/src/@types/type.properties.ts +75 -0
  107. package/src/@types/types.attributes.ts +28 -0
  108. package/src/@types/types.compiled.ts +35 -0
  109. package/src/@types/types.hash.ts +24 -0
  110. package/src/@types/types.hvtec.ts +25 -0
  111. package/src/@types/types.pvtec.ts +30 -0
  112. package/src/@types/types.settings.ts +76 -0
  113. package/src/@types/types.stanza.ts +37 -0
  114. package/src/@types/types.ugc.ts +24 -0
  115. package/src/@types/types.webhook.ts +26 -0
  116. package/src/bootstrap.ts +85 -163
  117. package/src/index.ts +47 -216
  118. package/test.js +78 -51
  119. package/tsup.config.ts +1 -0
  120. package/src/@dictionaries/events.ts +0 -168
  121. package/src/@parsers/@events/api.ts +0 -146
  122. package/src/@parsers/@events/cap.ts +0 -123
  123. package/src/@parsers/@events/text.ts +0 -104
  124. package/src/@parsers/@events/ugc.ts +0 -107
  125. package/src/@parsers/@events/vtec.ts +0 -76
  126. package/src/@parsers/events.ts +0 -392
  127. package/src/@parsers/hvtec.ts +0 -46
  128. package/src/@parsers/pvtec.ts +0 -72
  129. package/src/@parsers/stanza.ts +0 -97
  130. package/src/@parsers/text.ts +0 -165
  131. package/src/@parsers/ugc.ts +0 -247
  132. package/src/@submodules/database.ts +0 -201
  133. package/src/@submodules/eas.ts +0 -490
  134. package/src/@submodules/utils.ts +0 -191
  135. package/src/@submodules/xmpp.ts +0 -142
  136. 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
+