@ozdemirburak/morse-code-translator 5.0.4 → 7.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/audio.ts DELETED
@@ -1,191 +0,0 @@
1
- const getGainTimings = (morse: string, opts: Options, currentTime = 0): [[[number, number]?], number] => {
2
- const timings: [[number, number]?] = [];
3
- let {unit, fwUnit} = opts;
4
- let time = 0;
5
-
6
- if (opts.wpm) {
7
- // wpm mode uses standardised units
8
- unit = fwUnit = 60 / (opts.wpm * 50)
9
- }
10
-
11
- timings.push([0, time]);
12
-
13
- const tone = (i: number) => {
14
- timings.push([1 * (opts.volume / 100.0), currentTime + time]);
15
- time += i * unit;
16
- };
17
-
18
- const silence = (i: number) => {
19
- timings.push([0, currentTime + time]);
20
- time += i * unit;
21
- };
22
-
23
- const gap = (i: number) => {
24
- timings.push([0, currentTime + time]);
25
- time += i * fwUnit;
26
- };
27
-
28
- for (let i = 0, addSilence = false; i <= morse.length; i++) {
29
- if (morse[i] === opts.space) {
30
- gap(7);
31
- addSilence = false;
32
- } else if (morse[i] === opts.dot) {
33
- if (addSilence) silence(1); else addSilence = true;
34
- tone(1);
35
- } else if (morse[i] === opts.dash) {
36
- if (addSilence) silence(1); else addSilence = true;
37
- tone(3);
38
- } else if (
39
- (typeof morse[i + 1] !== 'undefined' && morse[i + 1] !== opts.space) &&
40
- (typeof morse[i - 1] !== 'undefined' && morse[i - 1] !== opts.space)
41
- ) {
42
- gap(3);
43
- addSilence = false;
44
- }
45
- }
46
-
47
- return [timings, time];
48
- };
49
-
50
- // Source: https://github.com/mattdiamond/Recorderjs/blob/master/src/recorder.js#L155
51
- const encodeWAV = (sampleRate: number, samples: Float32Array) => {
52
- const buffer = new ArrayBuffer(44 + samples.length * 2);
53
- const view = new DataView(buffer);
54
- const writeString = (view: DataView, offset: number, string: string) => {
55
- for (let i = 0; i < string.length; i++) {
56
- view.setUint8(offset + i, string.charCodeAt(i));
57
- }
58
- };
59
- // RIFF identifier
60
- writeString(view, 0, 'RIFF');
61
- // RIFF chunk length
62
- view.setUint32(4, 36 + samples.length * 2, true);
63
- // RIFF type
64
- writeString(view, 8, 'WAVE');
65
- // format chunk identifier
66
- writeString(view, 12, 'fmt ');
67
- // format chunk length
68
- view.setUint32(16, 16, true);
69
- // sample format (raw)
70
- view.setUint16(20, 1, true);
71
- // channel count
72
- view.setUint16(22, 1, true);
73
- // sample rate
74
- view.setUint32(24, sampleRate, true);
75
- // byte rate (sample rate * block align)
76
- view.setUint32(28, sampleRate * 4, true);
77
- // block align (channel count * bytes per sample)
78
- view.setUint16(32, 2, true);
79
- // bits per sample
80
- view.setUint16(34, 16, true);
81
- // data chunk identifier
82
- writeString(view, 36, 'data');
83
- // data chunk length
84
- view.setUint32(40, samples.length * 2, true);
85
- // to PCM
86
- const floatTo16BitPCM = (output: DataView, offset: number, input: Float32Array) => {
87
- for (let i = 0; i < input.length; i++, offset += 2) {
88
- const s = Math.max(-1, Math.min(1, input[i]));
89
- output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
90
- }
91
- };
92
- floatTo16BitPCM(view, 44, samples);
93
- return view;
94
- };
95
-
96
- const audio = (morse: string, options: Options) => {
97
- let AudioContextClass = window.AudioContext || (window as any).webkitAudioContext;
98
- let OfflineAudioContextClass = window.OfflineAudioContext || (window as any).webkitOfflineAudioContext;
99
-
100
- if (!AudioContextClass || !OfflineAudioContextClass) {
101
- throw new Error('Web Audio API is not supported in this browser');
102
- }
103
-
104
- const context = new AudioContextClass();
105
- const [gainValues, totalTime] = getGainTimings(morse, options);
106
- const offlineContext = new OfflineAudioContextClass(1, 44100 * totalTime, 44100);
107
-
108
- const oscillator = offlineContext.createOscillator();
109
- const gainNode = offlineContext.createGain();
110
-
111
- oscillator.type = options.oscillator.type as OscillatorType;
112
- oscillator.frequency.value = options.oscillator.frequency;
113
-
114
- gainValues.forEach(([value, time]) => gainNode.gain.setValueAtTime(value, time));
115
-
116
- oscillator.connect(gainNode);
117
- gainNode.connect(offlineContext.destination);
118
-
119
- let source: AudioBufferSourceNode;
120
-
121
- // Render the audio buffer
122
- const render = new Promise<void>((resolve, reject) => {
123
- oscillator.start(0);
124
- offlineContext.startRendering();
125
- offlineContext.oncomplete = (e) => {
126
- try {
127
- source = context.createBufferSource();
128
- source.buffer = e.renderedBuffer;
129
- source.connect(context.destination);
130
- source.onended = options.oscillator.onended;
131
- resolve();
132
- } catch (err) {
133
- reject(err);
134
- }
135
- };
136
- offlineContext.onerror = (err) => {
137
- reject(err);
138
- };
139
- });
140
-
141
- let timeout: number;
142
-
143
- const play = async () => {
144
- await render;
145
- if (context.state === 'suspended') {
146
- await context.resume();
147
- }
148
- source.start(context.currentTime);
149
- timeout = window.setTimeout(() => { stop(); }, totalTime * 1000);
150
- };
151
-
152
- const stop = () => {
153
- clearTimeout(timeout);
154
- if (source) {
155
- source.stop(0);
156
- }
157
- };
158
-
159
- const getWaveBlob = async () => {
160
- await render;
161
- const waveData = encodeWAV(offlineContext.sampleRate, source.buffer.getChannelData(0));
162
- return new Blob([waveData], { type: 'audio/wav' });
163
- };
164
-
165
- const getWaveUrl = async () => {
166
- const audioBlob = await getWaveBlob();
167
- return URL.createObjectURL(audioBlob);
168
- };
169
-
170
- const exportWave = async (filename: string) => {
171
- const waveUrl = await getWaveUrl();
172
- const anchor = document.createElement('a');
173
- anchor.href = waveUrl;
174
- anchor.target = '_blank';
175
- anchor.download = filename || 'morse.wav';
176
- anchor.click();
177
- };
178
-
179
- return {
180
- play,
181
- stop,
182
- getWaveBlob,
183
- getWaveUrl,
184
- exportWave,
185
- context,
186
- oscillator,
187
- gainNode
188
- };
189
- };
190
-
191
- export default audio;
package/src/characters.ts DELETED
@@ -1,139 +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://ko.wikipedia.org/wiki/%EB%AA%A8%EC%8A%A4_%EB%B6%80%ED%98%B8
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
- 'ㅐ': '1101', 'ㅔ': '1011'
82
- },
83
- '12': { // Thai Alphabet => https://th.wikipedia.org/wiki/รหัสมอร์ส
84
- 'ก': '110', 'ข': '1010', 'ค': '101', 'ง': '10110', 'จ': '10010',
85
- 'ฉ': '1111', 'ช': '1001', 'ซ': '1100', 'ญ': '0111', 'ด': '100',
86
- 'ต': '1', 'ถ': '10100', 'ท': '10011', 'น': '10', 'บ': '1000',
87
- 'ป': '0110', 'ผ': '1101', 'ฝ': '10101', 'พ': '01100', 'ฟ': '0010',
88
- 'ม': '11', 'ย': '1011', 'ร': '010', 'ล': '0100', 'ว': '011',
89
- 'ส': '000', 'ห': '0000', 'อ': '10001', 'ฮ': '11011', 'ฤ': '01011',
90
- 'ะ': '01000', 'า': '01', 'ิ': '00100', 'ี': '00', 'ึ': '00110',
91
- 'ื': '0011', 'ุ': '00101', 'ู': '1110', 'เ': '0', 'แ': '0101',
92
- 'ไ': '01001', 'โ': '111', 'ำ': '00010', '่': '001', '้': '0001',
93
- '๊': '11000', '๋': '01010', 'ั': '01101', '็': '11100', '์': '11001',
94
- 'ๆ': '10111', 'ฯ': '11010'
95
- }
96
- };
97
-
98
- const getCharacters = (options: Options) => ({
99
- ...baseCharacters,
100
- '0': baseCharacters[options.priority],
101
- '1': {
102
- ...baseCharacters['1'],
103
- [options.separator]: options.space
104
- }
105
- });
106
-
107
- const getMappedCharacters = (options: Options, usePriority: boolean) => {
108
- const mapped: Characters = {};
109
- const characters = getCharacters(options);
110
- for (const set in characters) {
111
- mapped[set] = {};
112
- for (const key in characters[set]) {
113
- mapped[set][key] = characters[set][key].replace(/0/g, options.dot).replace(/1/g, options.dash);
114
- }
115
- }
116
- if (!usePriority) {
117
- delete mapped['0'];
118
- }
119
- return mapped;
120
- };
121
-
122
- const swapCharacters = (options: Options) => {
123
- const swapped: Record<string, string> = {};
124
- const mappedCharacters = getMappedCharacters(options, true);
125
- for (const set in mappedCharacters) {
126
- for (const key in mappedCharacters[set]) {
127
- if (typeof swapped[mappedCharacters[set][key]] === 'undefined') {
128
- swapped[mappedCharacters[set][key]] = key;
129
- }
130
- }
131
- }
132
- return swapped;
133
- };
134
-
135
- export {
136
- getCharacters,
137
- getMappedCharacters,
138
- swapCharacters
139
- };
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
- }