@ozdemirburak/morse-code-translator 5.0.3 → 6.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/characters.ts DELETED
@@ -1,138 +0,0 @@
1
- const baseCharacters: Characters = {
2
- '1': { // Latin => https://en.wikipedia.org/wiki/Morse_code
3
- 'A': '01', 'B': '1000', 'C': '1010', 'D': '100', 'E': '0', 'F': '0010',
4
- 'G': '110', 'H': '0000', 'I': '00', 'J': '0111', 'K': '101', 'L': '0100',
5
- 'M': '11', 'N': '10', 'O': '111', 'P': '0110', 'Q': '1101', 'R': '010',
6
- 'S': '000', 'T': '1', 'U': '001', 'V': '0001', 'W': '011', 'X': '1001',
7
- 'Y': '1011', 'Z': '1100'
8
- },
9
- '2': { // Numbers
10
- '0': '11111', '1': '01111', '2': '00111', '3': '00011', '4': '00001',
11
- '5': '00000', '6': '10000', '7': '11000', '8': '11100', '9': '11110'
12
- },
13
- '3': { // Punctuation
14
- '.': '010101', ',': '110011', '?': '001100', '\'': '011110', '!': '101011', '/': '10010',
15
- '(': '10110', ')': '101101', '&': '01000', ':': '111000', ';': '101010', '=': '10001',
16
- '+': '01010', '-': '100001', '_': '001101', '"': '010010', '$': '0001001', '@': '011010',
17
- '¿': '00101', '¡': '110001'
18
- },
19
- '4': { // Latin Extended => https://ham.stackexchange.com/questions/1379/international-characters-in-morse-code
20
- 'Ã': '01101', 'Á': '01101', 'Å': '01101', 'À': '01101', 'Â': '01101', 'Ä': '0101',
21
- 'Ą': '0101', 'Æ': '0101', 'Ç': '10100', 'Ć': '10100', 'Ĉ': '10100', 'Č': '110',
22
- 'Ð': '00110', 'È': '01001', 'Ę': '00100', 'Ë': '00100', 'É': '00100',
23
- 'Ê': '10010', 'Ğ': '11010', 'Ĝ': '11010', 'Ĥ': '1111', 'İ': '01001', 'Ï': '10011',
24
- 'Ì': '01110', 'Ĵ': '01110', 'Ł': '01001', 'Ń': '11011', 'Ñ': '11011', 'Ó': '1110',
25
- 'Ò': '1110', 'Ö': '1110', 'Ô': '1110', 'Ø': '1110', 'Ś': '0001000', 'Ş': '01100',
26
- 'Ș': '1111', 'Š': '1111', 'Ŝ': '00010', 'ß': '000000', 'Þ': '01100', 'Ü': '0011',
27
- 'Ù': '0011', 'Ŭ': '0011', 'Ž': '11001', 'Ź': '110010', 'Ż': '11001'
28
- },
29
- '5': { // Cyrillic Alphabet => https://en.wikipedia.org/wiki/Russian_Morse_code
30
- 'А': '01', 'Б': '1000', 'В': '011', 'Г': '110', 'Д': '100', 'Е': '0',
31
- 'Ж': '0001', 'З': '1100', 'И': '00', 'Й': '0111', 'К': '101', 'Л': '0100',
32
- 'М': '11', 'Н': '10', 'О': '111', 'П': '0110', 'Р': '010', 'С': '000',
33
- 'Т': '1', 'У': '001', 'Ф': '0010', 'Х': '0000', 'Ц': '1010', 'Ч': '1110',
34
- 'Ш': '1111', 'Щ': '1101', 'Ъ': '11011', 'Ы': '1011', 'Ь': '1001', 'Э': '00100',
35
- 'Ю': '0011', 'Я': '0101', 'Ї': '01110', 'Є': '00100', 'І': '00', 'Ґ': '110'
36
- },
37
- '6': { // Greek Alphabet => https://en.wikipedia.org/wiki/Morse_code_for_non-Latin_alphabets
38
- 'Α': '01', 'Β': '1000', 'Γ': '110', 'Δ': '100', 'Ε': '0', 'Ζ': '1100',
39
- 'Η': '0000', 'Θ': '1010', 'Ι': '00', 'Κ': '101', 'Λ': '0100', 'Μ': '11',
40
- 'Ν': '10', 'Ξ': '1001', 'Ο': '111', 'Π': '0110', 'Ρ': '010', 'Σ': '000',
41
- 'Τ': '1', 'Υ': '1011', 'Φ': '0010', 'Χ': '1111', 'Ψ': '1101', 'Ω': '011'
42
- },
43
- '7': { // Hebrew Alphabet => https://en.wikipedia.org/wiki/Morse_code_for_non-Latin_alphabets
44
- 'א': '01', 'ב': '1000', 'ג': '110', 'ד': '100', 'ה': '111', 'ו': '0',
45
- 'ז': '1100', 'ח': '0000', 'ט': '001', 'י': '00', 'כ': '101', 'ל': '0100',
46
- 'מ': '11', 'נ': '10', 'ס': '1010', 'ע': '0111', 'פ': '0110', 'צ': '011',
47
- 'ק': '1101', 'ר': '010', 'ש': '000', 'ת': '1'
48
- },
49
- '8': { // Arabic Alphabet => https://en.wikipedia.org/wiki/Morse_code_for_non-Latin_alphabets
50
- 'ا': '01', 'ب': '1000', 'ت': '1', 'ث': '1010', 'ج': '0111', 'ح': '0000',
51
- 'خ': '111', 'د': '100', 'ذ': '1100', 'ر': '010', 'ز': '1110', 'س': '000',
52
- 'ش': '1111', 'ص': '1001', 'ض': '0001', 'ط': '001', 'ظ': '1011', 'ع': '0101',
53
- 'غ': '110', 'ف': '0010', 'ق': '1101', 'ك': '101', 'ل': '0100', 'م': '11',
54
- 'ن': '10', 'ه': '00100', 'و': '011', 'ي': '00', 'ﺀ': '0'
55
- },
56
- '9': { // Persian Alphabet => https://en.wikipedia.org/wiki/Morse_code_for_non-Latin_alphabets
57
- 'ا': '01', 'ب': '1000', 'پ': '0110', 'ت': '1', 'ث': '1010', 'ج': '0111',
58
- 'چ': '1110', 'ح': '0000', 'خ': '1001', 'د': '100', 'ذ': '0001', 'ر': '010',
59
- 'ز': '1100', 'ژ': '110', 'س': '000', 'ش': '1111', 'ص': '0101', 'ض': '00100',
60
- 'ط': '001', 'ظ': '1011', 'ع': '111', 'غ': '0011', 'ف': '0010', 'ق': '111000',
61
- 'ک': '101', 'گ': '1101', 'ل': '0100', 'م': '11', 'ن': '10', 'و': '011',
62
- 'ه': '0', 'ی': '00'
63
- },
64
- '10': { // Japanese Alphabet => https://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%BC%E3%83%AB%E3%82%B9%E7%AC%A6%E5%8F%B7#%E5%92%8C%E6%96%87%E3%83%A2%E3%83%BC%E3%83%AB%E3%82%B9%E7%AC%A6%E5%8F%B7
65
- 'ア': '11011', 'カ': '0100', 'サ': '10101', 'タ': '10', 'ナ': '010', 'ハ': '1000',
66
- 'マ': '1001', 'ヤ': '011', 'ラ': '000', 'ワ': '101', 'イ': '01', 'キ': '10100',
67
- 'シ': '11010', 'チ': '0010', 'ニ': '1010', 'ヒ': '11001', 'ミ': '00101', 'リ': '110',
68
- 'ヰ': '01001', 'ウ': '001', 'ク': '0001', 'ス': '11101', 'ツ': '0110', 'ヌ': '0000',
69
- 'フ': '1100', 'ム': '1', 'ユ': '10011', 'ル': '10110', 'ン': '01010', 'エ': '10111',
70
- 'ケ': '1011', 'セ': '01110', 'テ': '01011', 'ネ': '1101', 'ヘ': '0', 'メ': '10001',
71
- 'レ': '111', 'ヱ': '01100', 'オ': '01000', 'コ': '1111', 'ソ': '1110', 'ト': '00100',
72
- 'ノ': '0011', 'ホ': '100', 'モ': '10010', 'ヨ': '11', 'ロ': '0101', 'ヲ': '0111',
73
- '゛': '00', '゜': '00110', '。': '010100', 'ー': '01101', '、': '010101',
74
- '(': '101101', ')': '010010'
75
- },
76
- '11': { // Korean Alphabet => https://en.wikipedia.org/wiki/SKATS
77
- 'ㄱ': '0100', 'ㄴ': '0010', 'ㄷ': '1000', 'ㄹ': '0001', 'ㅁ': '11', 'ㅂ': '011',
78
- 'ㅅ': '110', 'ㅇ': '101', 'ㅈ': '0110', 'ㅊ': '1010', 'ㅋ': '1001', 'ㅌ': '1100',
79
- 'ㅍ': '111', 'ㅎ': '0111', 'ㅏ': '0', 'ㅑ': '00', 'ㅓ': '1', 'ㅕ': '000',
80
- 'ㅗ': '01', 'ㅛ': '10', 'ㅜ': '0000', 'ㅠ': '010', 'ㅡ': '100', 'ㅣ': '001'
81
- },
82
- '12': { // Thai Alphabet => https://th.wikipedia.org/wiki/รหัสมอร์ส
83
- 'ก': '110', 'ข': '1010', 'ค': '101', 'ง': '10110', 'จ': '10010',
84
- 'ฉ': '1111', 'ช': '1001', 'ซ': '1100', 'ญ': '0111', 'ด': '100',
85
- 'ต': '1', 'ถ': '10100', 'ท': '10011', 'น': '10', 'บ': '1000',
86
- 'ป': '0110', 'ผ': '1101', 'ฝ': '10101', 'พ': '01100', 'ฟ': '0010',
87
- 'ม': '11', 'ย': '1011', 'ร': '010', 'ล': '0100', 'ว': '011',
88
- 'ส': '000', 'ห': '0000', 'อ': '10001', 'ฮ': '11011', 'ฤ': '01011',
89
- 'ะ': '01000', 'า': '01', 'ิ': '00100', 'ี': '00', 'ึ': '00110',
90
- 'ื': '0011', 'ุ': '00101', 'ู': '1110', 'เ': '0', 'แ': '0101',
91
- 'ไ': '01001', 'โ': '111', 'ำ': '00010', '่': '001', '้': '0001',
92
- '๊': '11000', '๋': '01010', 'ั': '01101', '็': '11100', '์': '11001',
93
- 'ๆ': '10111', 'ฯ': '11010'
94
- }
95
- };
96
-
97
- const getCharacters = (options: Options) => ({
98
- ...baseCharacters,
99
- '0': baseCharacters[options.priority],
100
- '1': {
101
- ...baseCharacters['1'],
102
- [options.separator]: options.space
103
- }
104
- });
105
-
106
- const getMappedCharacters = (options: Options, usePriority: boolean) => {
107
- const mapped: Characters = {};
108
- const characters = getCharacters(options);
109
- for (const set in characters) {
110
- mapped[set] = {};
111
- for (const key in characters[set]) {
112
- mapped[set][key] = characters[set][key].replace(/0/g, options.dot).replace(/1/g, options.dash);
113
- }
114
- }
115
- if (!usePriority) {
116
- delete mapped['0'];
117
- }
118
- return mapped;
119
- };
120
-
121
- const swapCharacters = (options: Options) => {
122
- const swapped: Record<string, string> = {};
123
- const mappedCharacters = getMappedCharacters(options, true);
124
- for (const set in mappedCharacters) {
125
- for (const key in mappedCharacters[set]) {
126
- if (typeof swapped[mappedCharacters[set][key]] === 'undefined') {
127
- swapped[mappedCharacters[set][key]] = key;
128
- }
129
- }
130
- }
131
- return swapped;
132
- };
133
-
134
- export {
135
- getCharacters,
136
- getMappedCharacters,
137
- swapCharacters
138
- };
package/src/index.d.ts DELETED
@@ -1,26 +0,0 @@
1
- interface Window {
2
- webkitAudioContext: typeof AudioContext
3
- webkitOfflineAudioContext: typeof OfflineAudioContext
4
- }
5
-
6
- type Characters = Record<string, Record<string, string>>
7
-
8
- interface Oscillator {
9
- type?: OscillatorType;
10
- frequency?: number;
11
- onended?: ((this: AudioScheduledSourceNode, ev: Event) => any) | null;
12
- }
13
-
14
- interface Options {
15
- dash: string;
16
- dot: string;
17
- space: string;
18
- separator: string;
19
- invalid: string;
20
- priority: number;
21
- wpm?: number;
22
- unit: number;
23
- fwUnit: number;
24
- volume: number;
25
- oscillator: Oscillator
26
- }
package/src/index.js DELETED
@@ -1,352 +0,0 @@
1
- 'use strict';
2
-
3
- const baseCharacters = {
4
- '1': {
5
- 'A': '01', 'B': '1000', 'C': '1010', 'D': '100', 'E': '0', 'F': '0010',
6
- 'G': '110', 'H': '0000', 'I': '00', 'J': '0111', 'K': '101', 'L': '0100',
7
- 'M': '11', 'N': '10', 'O': '111', 'P': '0110', 'Q': '1101', 'R': '010',
8
- 'S': '000', 'T': '1', 'U': '001', 'V': '0001', 'W': '011', 'X': '1001',
9
- 'Y': '1011', 'Z': '1100'
10
- },
11
- '2': {
12
- '0': '11111', '1': '01111', '2': '00111', '3': '00011', '4': '00001',
13
- '5': '00000', '6': '10000', '7': '11000', '8': '11100', '9': '11110'
14
- },
15
- '3': {
16
- '.': '010101', ',': '110011', '?': '001100', '\'': '011110', '!': '101011', '/': '10010',
17
- '(': '10110', ')': '101101', '&': '01000', ':': '111000', ';': '101010', '=': '10001',
18
- '+': '01010', '-': '100001', '_': '001101', '"': '010010', '$': '0001001', '@': '011010',
19
- '¿': '00101', '¡': '110001'
20
- },
21
- '4': {
22
- 'Ã': '01101', 'Á': '01101', 'Å': '01101', 'À': '01101', 'Â': '01101', 'Ä': '0101',
23
- 'Ą': '0101', 'Æ': '0101', 'Ç': '10100', 'Ć': '10100', 'Ĉ': '10100', 'Č': '110',
24
- 'Ð': '00110', 'È': '01001', 'Ę': '00100', 'Ë': '00100', 'É': '00100',
25
- 'Ê': '10010', 'Ğ': '11010', 'Ĝ': '11010', 'Ĥ': '1111', 'İ': '01001', 'Ï': '10011',
26
- 'Ì': '01110', 'Ĵ': '01110', 'Ł': '01001', 'Ń': '11011', 'Ñ': '11011', 'Ó': '1110',
27
- 'Ò': '1110', 'Ö': '1110', 'Ô': '1110', 'Ø': '1110', 'Ś': '0001000', 'Ş': '01100',
28
- 'Ș': '1111', 'Š': '1111', 'Ŝ': '00010', 'ß': '000000', 'Þ': '01100', 'Ü': '0011',
29
- 'Ù': '0011', 'Ŭ': '0011', 'Ž': '11001', 'Ź': '110010', 'Ż': '11001'
30
- },
31
- '5': {
32
- 'А': '01', 'Б': '1000', 'В': '011', 'Г': '110', 'Д': '100', 'Е': '0',
33
- 'Ж': '0001', 'З': '1100', 'И': '00', 'Й': '0111', 'К': '101', 'Л': '0100',
34
- 'М': '11', 'Н': '10', 'О': '111', 'П': '0110', 'Р': '010', 'С': '000',
35
- 'Т': '1', 'У': '001', 'Ф': '0010', 'Х': '0000', 'Ц': '1010', 'Ч': '1110',
36
- 'Ш': '1111', 'Щ': '1101', 'Ъ': '11011', 'Ы': '1011', 'Ь': '1001', 'Э': '00100',
37
- 'Ю': '0011', 'Я': '0101', 'Ї': '01110', 'Є': '00100', 'І': '00', 'Ґ': '110'
38
- },
39
- '6': {
40
- 'Α': '01', 'Β': '1000', 'Γ': '110', 'Δ': '100', 'Ε': '0', 'Ζ': '1100',
41
- 'Η': '0000', 'Θ': '1010', 'Ι': '00', 'Κ': '101', 'Λ': '0100', 'Μ': '11',
42
- 'Ν': '10', 'Ξ': '1001', 'Ο': '111', 'Π': '0110', 'Ρ': '010', 'Σ': '000',
43
- 'Τ': '1', 'Υ': '1011', 'Φ': '0010', 'Χ': '1111', 'Ψ': '1101', 'Ω': '011'
44
- },
45
- '7': {
46
- 'א': '01', 'ב': '1000', 'ג': '110', 'ד': '100', 'ה': '111', 'ו': '0',
47
- 'ז': '1100', 'ח': '0000', 'ט': '001', 'י': '00', 'כ': '101', 'ל': '0100',
48
- 'מ': '11', 'נ': '10', 'ס': '1010', 'ע': '0111', 'פ': '0110', 'צ': '011',
49
- 'ק': '1101', 'ר': '010', 'ש': '000', 'ת': '1'
50
- },
51
- '8': {
52
- 'ا': '01', 'ب': '1000', 'ت': '1', 'ث': '1010', 'ج': '0111', 'ح': '0000',
53
- 'خ': '111', 'د': '100', 'ذ': '1100', 'ر': '010', 'ز': '1110', 'س': '000',
54
- 'ش': '1111', 'ص': '1001', 'ض': '0001', 'ط': '001', 'ظ': '1011', 'ع': '0101',
55
- 'غ': '110', 'ف': '0010', 'ق': '1101', 'ك': '101', 'ل': '0100', 'م': '11',
56
- 'ن': '10', 'ه': '00100', 'و': '011', 'ي': '00', 'ﺀ': '0'
57
- },
58
- '9': {
59
- 'ا': '01', 'ب': '1000', 'پ': '0110', 'ت': '1', 'ث': '1010', 'ج': '0111',
60
- 'چ': '1110', 'ح': '0000', 'خ': '1001', 'د': '100', 'ذ': '0001', 'ر': '010',
61
- 'ز': '1100', 'ژ': '110', 'س': '000', 'ش': '1111', 'ص': '0101', 'ض': '00100',
62
- 'ط': '001', 'ظ': '1011', 'ع': '111', 'غ': '0011', 'ف': '0010', 'ق': '111000',
63
- 'ک': '101', 'گ': '1101', 'ل': '0100', 'م': '11', 'ن': '10', 'و': '011',
64
- 'ه': '0', 'ی': '00'
65
- },
66
- '10': {
67
- 'ア': '11011', 'カ': '0100', 'サ': '10101', 'タ': '10', 'ナ': '010', 'ハ': '1000',
68
- 'マ': '1001', 'ヤ': '011', 'ラ': '000', 'ワ': '101', 'イ': '01', 'キ': '10100',
69
- 'シ': '11010', 'チ': '0010', 'ニ': '1010', 'ヒ': '11001', 'ミ': '00101', 'リ': '110',
70
- 'ヰ': '01001', 'ウ': '001', 'ク': '0001', 'ス': '11101', 'ツ': '0110', 'ヌ': '0000',
71
- 'フ': '1100', 'ム': '1', 'ユ': '10011', 'ル': '10110', 'ン': '01010', 'エ': '10111',
72
- 'ケ': '1011', 'セ': '01110', 'テ': '01011', 'ネ': '1101', 'ヘ': '0', 'メ': '10001',
73
- 'レ': '111', 'ヱ': '01100', 'オ': '01000', 'コ': '1111', 'ソ': '1110', 'ト': '00100',
74
- 'ノ': '0011', 'ホ': '100', 'モ': '10010', 'ヨ': '11', 'ロ': '0101', 'ヲ': '0111',
75
- '゛': '00', '゜': '00110', '。': '010100', 'ー': '01101', '、': '010101',
76
- '(': '101101', ')': '010010'
77
- },
78
- '11': {
79
- 'ㄱ': '0100', 'ㄴ': '0010', 'ㄷ': '1000', 'ㄹ': '0001', 'ㅁ': '11', 'ㅂ': '011',
80
- 'ㅅ': '110', 'ㅇ': '101', 'ㅈ': '0110', 'ㅊ': '1010', 'ㅋ': '1001', 'ㅌ': '1100',
81
- 'ㅍ': '111', 'ㅎ': '0111', 'ㅏ': '0', 'ㅑ': '00', 'ㅓ': '1', 'ㅕ': '000',
82
- 'ㅗ': '01', 'ㅛ': '10', 'ㅜ': '0000', 'ㅠ': '010', 'ㅡ': '100', 'ㅣ': '001'
83
- },
84
- '12': {
85
- 'ก': '110', 'ข': '1010', 'ค': '101', 'ง': '10110', 'จ': '10010',
86
- 'ฉ': '1111', 'ช': '1001', 'ซ': '1100', 'ญ': '0111', 'ด': '100',
87
- 'ต': '1', 'ถ': '10100', 'ท': '10011', 'น': '10', 'บ': '1000',
88
- 'ป': '0110', 'ผ': '1101', 'ฝ': '10101', 'พ': '01100', 'ฟ': '0010',
89
- 'ม': '11', 'ย': '1011', 'ร': '010', 'ล': '0100', 'ว': '011',
90
- 'ส': '000', 'ห': '0000', 'อ': '10001', 'ฮ': '11011', 'ฤ': '01011',
91
- 'ะ': '01000', 'า': '01', 'ิ': '00100', 'ี': '00', 'ึ': '00110',
92
- 'ื': '0011', 'ุ': '00101', 'ู': '1110', 'เ': '0', 'แ': '0101',
93
- 'ไ': '01001', 'โ': '111', 'ำ': '00010', '่': '001', '้': '0001',
94
- '๊': '11000', '๋': '01010', 'ั': '01101', '็': '11100', '์': '11001',
95
- 'ๆ': '10111', 'ฯ': '11010'
96
- }
97
- };
98
- const getCharacters = (options) => (Object.assign(Object.assign({}, baseCharacters), { '0': baseCharacters[options.priority], '1': Object.assign(Object.assign({}, baseCharacters['1']), { [options.separator]: options.space }) }));
99
- const getMappedCharacters = (options, usePriority) => {
100
- const mapped = {};
101
- const characters = getCharacters(options);
102
- for (const set in characters) {
103
- mapped[set] = {};
104
- for (const key in characters[set]) {
105
- mapped[set][key] = characters[set][key].replace(/0/g, options.dot).replace(/1/g, options.dash);
106
- }
107
- }
108
- if (!usePriority) {
109
- delete mapped['0'];
110
- }
111
- return mapped;
112
- };
113
- const swapCharacters = (options) => {
114
- const swapped = {};
115
- const mappedCharacters = getMappedCharacters(options, true);
116
- for (const set in mappedCharacters) {
117
- for (const key in mappedCharacters[set]) {
118
- if (typeof swapped[mappedCharacters[set][key]] === 'undefined') {
119
- swapped[mappedCharacters[set][key]] = key;
120
- }
121
- }
122
- }
123
- return swapped;
124
- };
125
-
126
- const getOptions = (opts = {}) => {
127
- var _a, _b, _c;
128
- const options = Object.assign(Object.assign({}, opts), { dash: opts.dash || '-', dot: opts.dot || '.', space: opts.space || '/', separator: opts.separator || ' ', invalid: opts.invalid || '#', priority: opts.priority || 1, wpm: opts.wpm, unit: opts.unit || 0.08, fwUnit: opts.fwUnit || opts.unit || 0.08, volume: opts.volume || 100, oscillator: Object.assign(Object.assign({}, opts.oscillator), { type: ((_a = opts.oscillator) === null || _a === void 0 ? void 0 : _a.type) || 'sine', frequency: ((_b = opts.oscillator) === null || _b === void 0 ? void 0 : _b.frequency) || 500, onended: ((_c = opts.oscillator) === null || _c === void 0 ? void 0 : _c.onended) || null // event that fires when the tone has stopped playing
129
- }) });
130
- return options;
131
- };
132
-
133
- const getGainTimings = (morse, opts, currentTime = 0) => {
134
- const timings = [];
135
- let { unit, fwUnit } = opts;
136
- let time = 0;
137
- if (opts.wpm) {
138
- // wpm mode uses standardised units
139
- unit = fwUnit = 60 / (opts.wpm * 50);
140
- }
141
- timings.push([0, time]);
142
- const tone = (i) => {
143
- timings.push([1 * (opts.volume / 100.0), currentTime + time]);
144
- time += i * unit;
145
- };
146
- const silence = (i) => {
147
- timings.push([0, currentTime + time]);
148
- time += i * unit;
149
- };
150
- const gap = (i) => {
151
- timings.push([0, currentTime + time]);
152
- time += i * fwUnit;
153
- };
154
- for (let i = 0, addSilence = false; i <= morse.length; i++) {
155
- if (morse[i] === opts.space) {
156
- gap(7);
157
- addSilence = false;
158
- }
159
- else if (morse[i] === opts.dot) {
160
- if (addSilence)
161
- silence(1);
162
- else
163
- addSilence = true;
164
- tone(1);
165
- }
166
- else if (morse[i] === opts.dash) {
167
- if (addSilence)
168
- silence(1);
169
- else
170
- addSilence = true;
171
- tone(3);
172
- }
173
- else if ((typeof morse[i + 1] !== 'undefined' && morse[i + 1] !== opts.space) &&
174
- (typeof morse[i - 1] !== 'undefined' && morse[i - 1] !== opts.space)) {
175
- gap(3);
176
- addSilence = false;
177
- }
178
- }
179
- return [timings, time];
180
- };
181
- // Source: https://github.com/mattdiamond/Recorderjs/blob/master/src/recorder.js#L155
182
- const encodeWAV = (sampleRate, samples) => {
183
- const buffer = new ArrayBuffer(44 + samples.length * 2);
184
- const view = new DataView(buffer);
185
- const writeString = (view, offset, string) => {
186
- for (let i = 0; i < string.length; i++) {
187
- view.setUint8(offset + i, string.charCodeAt(i));
188
- }
189
- };
190
- // RIFF identifier
191
- writeString(view, 0, 'RIFF');
192
- // RIFF chunk length
193
- view.setUint32(4, 36 + samples.length * 2, true);
194
- // RIFF type
195
- writeString(view, 8, 'WAVE');
196
- // format chunk identifier
197
- writeString(view, 12, 'fmt ');
198
- // format chunk length
199
- view.setUint32(16, 16, true);
200
- // sample format (raw)
201
- view.setUint16(20, 1, true);
202
- // channel count
203
- view.setUint16(22, 1, true);
204
- // sample rate
205
- view.setUint32(24, sampleRate, true);
206
- // byte rate (sample rate * block align)
207
- view.setUint32(28, sampleRate * 4, true);
208
- // block align (channel count * bytes per sample)
209
- view.setUint16(32, 2, true);
210
- // bits per sample
211
- view.setUint16(34, 16, true);
212
- // data chunk identifier
213
- writeString(view, 36, 'data');
214
- // data chunk length
215
- view.setUint32(40, samples.length * 2, true);
216
- // to PCM
217
- const floatTo16BitPCM = (output, offset, input) => {
218
- for (let i = 0; i < input.length; i++, offset += 2) {
219
- const s = Math.max(-1, Math.min(1, input[i]));
220
- output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
221
- }
222
- };
223
- floatTo16BitPCM(view, 44, samples);
224
- return view;
225
- };
226
- const audio = (morse, options) => {
227
- let AudioContextClass = window.AudioContext || window.webkitAudioContext;
228
- let OfflineAudioContextClass = window.OfflineAudioContext || window.webkitOfflineAudioContext;
229
- if (!AudioContextClass || !OfflineAudioContextClass) {
230
- throw new Error('Web Audio API is not supported in this browser');
231
- }
232
- const context = new AudioContextClass();
233
- const [gainValues, totalTime] = getGainTimings(morse, options);
234
- const offlineContext = new OfflineAudioContextClass(1, 44100 * totalTime, 44100);
235
- const oscillator = offlineContext.createOscillator();
236
- const gainNode = offlineContext.createGain();
237
- oscillator.type = options.oscillator.type;
238
- oscillator.frequency.value = options.oscillator.frequency;
239
- gainValues.forEach(([value, time]) => gainNode.gain.setValueAtTime(value, time));
240
- oscillator.connect(gainNode);
241
- gainNode.connect(offlineContext.destination);
242
- let source;
243
- // Render the audio buffer
244
- const render = new Promise((resolve, reject) => {
245
- oscillator.start(0);
246
- offlineContext.startRendering();
247
- offlineContext.oncomplete = (e) => {
248
- try {
249
- source = context.createBufferSource();
250
- source.buffer = e.renderedBuffer;
251
- source.connect(context.destination);
252
- source.onended = options.oscillator.onended;
253
- resolve();
254
- }
255
- catch (err) {
256
- reject(err);
257
- }
258
- };
259
- offlineContext.onerror = (err) => {
260
- reject(err);
261
- };
262
- });
263
- let timeout;
264
- const play = async () => {
265
- await render;
266
- if (context.state === 'suspended') {
267
- await context.resume();
268
- }
269
- source.start(context.currentTime);
270
- timeout = window.setTimeout(() => { stop(); }, totalTime * 1000);
271
- };
272
- const stop = () => {
273
- clearTimeout(timeout);
274
- if (source) {
275
- source.stop(0);
276
- }
277
- };
278
- const getWaveBlob = async () => {
279
- await render;
280
- const waveData = encodeWAV(offlineContext.sampleRate, source.buffer.getChannelData(0));
281
- return new Blob([waveData], { type: 'audio/wav' });
282
- };
283
- const getWaveUrl = async () => {
284
- const audioBlob = await getWaveBlob();
285
- return URL.createObjectURL(audioBlob);
286
- };
287
- const exportWave = async (filename) => {
288
- const waveUrl = await getWaveUrl();
289
- const anchor = document.createElement('a');
290
- anchor.href = waveUrl;
291
- anchor.target = '_blank';
292
- anchor.download = filename || 'morse.wav';
293
- anchor.click();
294
- };
295
- return {
296
- play,
297
- stop,
298
- getWaveBlob,
299
- getWaveUrl,
300
- exportWave,
301
- context,
302
- oscillator,
303
- gainNode
304
- };
305
- };
306
-
307
- (((name, root, factory) => {
308
- if (typeof exports === 'object') {
309
- module.exports = factory();
310
- }
311
- else if (typeof define === 'function' && define.amd) {
312
- define(factory);
313
- }
314
- else if (root !== undefined) {
315
- root[name] = factory();
316
- }
317
- })('morse-code-translator', globalThis, () => {
318
- const encode = (text, opts) => {
319
- const options = getOptions(opts);
320
- const characters = getCharacters(options);
321
- return [...text.replace(/\s+/g, options.separator).trim().toLocaleUpperCase()].map(function (character) {
322
- for (const set in characters) {
323
- if (typeof characters[set] !== 'undefined' && typeof characters[set][character] !== 'undefined') {
324
- return characters[set][character];
325
- }
326
- }
327
- return options.invalid;
328
- }).join(options.separator).replace(/0/g, options.dot).replace(/1/g, options.dash);
329
- };
330
- const decode = (morse, opts) => {
331
- const options = getOptions(opts);
332
- const swapped = swapCharacters(options);
333
- return morse.replace(/\s+/g, options.separator).trim().split(options.separator).map(function (characters) {
334
- if (typeof swapped[characters] !== 'undefined') {
335
- return swapped[characters];
336
- }
337
- return options.invalid;
338
- }).join('');
339
- };
340
- const characters = (options, usePriority) => getMappedCharacters(getOptions(options), usePriority);
341
- const audio$1 = (text, opts, morseString) => {
342
- const morse = morseString || encode(text, opts);
343
- const options = getOptions(opts);
344
- return audio(morse, options);
345
- };
346
- return {
347
- characters,
348
- decode,
349
- encode,
350
- audio: audio$1
351
- };
352
- }));
package/src/index.ts DELETED
@@ -1,58 +0,0 @@
1
- import { getCharacters, getMappedCharacters, swapCharacters } from './characters';
2
- import getOptions from './options';
3
- import getAudio from './audio';
4
-
5
- declare let exports;
6
- declare let module;
7
- declare let define;
8
-
9
- ;(((name, root, factory) => {
10
- if (typeof exports === 'object') {
11
- module.exports = factory();
12
- } else if (typeof define === 'function' && define.amd) {
13
- define(factory);
14
- } else if (root !== undefined) {
15
- root[name] = factory();
16
- }
17
- })('morse-code-translator', globalThis, () => {
18
- 'use strict';
19
-
20
- const encode = (text: string, opts: Options) => {
21
- const options = getOptions(opts);
22
- const characters = getCharacters(options);
23
- return [...text.replace(/\s+/g, options.separator).trim().toLocaleUpperCase()].map(function (character) {
24
- for (const set in characters) {
25
- if (typeof characters[set] !== 'undefined' && typeof characters[set][character] !== 'undefined') {
26
- return characters[set][character];
27
- }
28
- }
29
- return options.invalid;
30
- }).join(options.separator).replace(/0/g, options.dot).replace(/1/g, options.dash);
31
- };
32
-
33
- const decode = (morse: string, opts: Options) => {
34
- const options = getOptions(opts);
35
- const swapped = swapCharacters(options);
36
- return morse.replace(/\s+/g, options.separator).trim().split(options.separator).map(function (characters) {
37
- if (typeof swapped[characters] !== 'undefined') {
38
- return swapped[characters];
39
- }
40
- return options.invalid;
41
- }).join('');
42
- };
43
-
44
- const characters = (options, usePriority) => getMappedCharacters(getOptions(options), usePriority);
45
-
46
- const audio = (text: string, opts: Options, morseString: string) => {
47
- const morse = morseString || encode(text, opts);
48
- const options = getOptions(opts);
49
- return getAudio(morse, options);
50
- }
51
-
52
- return {
53
- characters,
54
- decode,
55
- encode,
56
- audio
57
- };
58
- }));
package/src/options.ts DELETED
@@ -1,24 +0,0 @@
1
- const getOptions = (opts: Partial<Options> = {}): Options => {
2
- const options: Options = {
3
- ...opts,
4
- dash: opts.dash || '-',
5
- dot: opts.dot || '.',
6
- space: opts.space || '/',
7
- separator: opts.separator || ' ',
8
- invalid: opts.invalid || '#',
9
- priority: opts.priority || 1,
10
- wpm: opts.wpm, // words per minute - PARIS method used in favour of unit/fwUnit options
11
- unit: opts.unit || 0.08, // period of one unit, in seconds, 1.2 / c where c is speed of transmission, in words per minute
12
- fwUnit: opts.fwUnit || opts.unit || 0.08, // Farnsworth unit to control intercharacter and interword gaps
13
- volume: opts.volume || 100,
14
- oscillator: {
15
- ...opts.oscillator,
16
- type: opts.oscillator?.type || 'sine', // sine, square, sawtooth, triangle
17
- frequency: opts.oscillator?.frequency || 500, // value in hertz
18
- onended: opts.oscillator?.onended || null // event that fires when the tone has stopped playing
19
- }
20
- };
21
- return options;
22
- };
23
-
24
- export default getOptions;