|
36 | 36 | 'Ș': '1111', 'Š': '1111', 'Ŝ': '00010', 'ß': '000000', 'Þ': '01100', 'Ü': '0011',
|
37 | 37 | 'Ù': '0011', 'Ŭ': '0011', 'Ž': '11001', 'Ź': '110010', 'Ż': '11001'
|
38 | 38 | },
|
39 |
| - '5': { // Cyrilic Alphabet => https://en.wikipedia.org/wiki/Russian_Morse_code |
| 39 | + '5': { // Cyrillic Alphabet => https://en.wikipedia.org/wiki/Russian_Morse_code |
40 | 40 | 'А': '01', 'Б': '1000', 'В': '011', 'Г': '110', 'Д': '100', 'Е': '0',
|
41 | 41 | 'Ж': '0001', 'З': '1100', 'И': '00', 'Й': '0111', 'К': '101','Л': '0100',
|
42 | 42 | 'М': '11', 'Н': '10', 'О': '111', 'П': '0110', 'Р': '010', 'С': '000',
|
|
105 | 105 |
|
106 | 106 | var getOptions = function (options) {
|
107 | 107 | options = options || {};
|
| 108 | + options.oscillator = options.oscillator || {}; |
108 | 109 | options = {
|
109 | 110 | dash: options.dash || '-',
|
110 | 111 | dot: options.dot || '.',
|
111 | 112 | space: options.space || '/',
|
112 | 113 | invalid: options.invalid || '#',
|
113 | 114 | priority: options.priority || 1,
|
114 |
| - channels: options.channels || 1, |
115 |
| - sampleRate: options.sampleRate || 1012, |
116 |
| - bitDepth: options.bitDepth || 16, |
117 |
| - unit: options.unit || 0.1, |
118 |
| - frequency: options.frequency || 440.0, |
119 |
| - volume: options.volume || 32767 |
| 115 | + unit: options.unit || 0.08, // period of one unit, in seconds, 1.2 / c where c is speed of transmission, in words per minute |
| 116 | + oscillator: { |
| 117 | + type: options.oscillator.type || 'sine', // sine, square, sawtooth, triangle |
| 118 | + frequency: options.oscillator.frequency || 500, // value in hertz |
| 119 | + onended: options.oscillator.onended || null, // event that fires when the tone has stopped playing |
| 120 | + } |
120 | 121 | };
|
121 | 122 | characters[0] = characters[options.priority];
|
122 | 123 | return options;
|
|
141 | 142 | }).join(' ').replace(/\s+/g, ' ');
|
142 | 143 | };
|
143 | 144 |
|
144 |
| - // Source: https://github.com/mattt/Morse.js |
145 | 145 | var audio = function (text, opts) {
|
146 |
| - var options = getOptions(opts), morse = encode(text, opts), data = [], samples = 0, |
147 |
| - pack = function (e) { |
148 |
| - for (var b = '', c = 1, d = 0; d < e.length; d++) { |
149 |
| - var f = e.charAt(d), a = arguments[c++]; |
150 |
| - b += f === 'v' ? String.fromCharCode(a & 255, a >> 8 & 255) : String.fromCharCode(a & 255, a >> 8 & 255, a >> 16 & 255, a >> 24 & 255); |
151 |
| - } |
152 |
| - return b; |
153 |
| - }, tone = function (length) { |
154 |
| - for (var i = 0; i < options.sampleRate * options.unit * length; i++) { |
155 |
| - for (var c = 0; c < options.channels; c++) { |
156 |
| - var v = options.volume * Math.sin((2 * Math.PI) * (i / options.sampleRate) * options.frequency); |
157 |
| - data.push(pack('v', v)); samples++; |
158 |
| - } |
159 |
| - } |
160 |
| - }, silence = function (length) { |
161 |
| - for (var i = 0; i < options.sampleRate * options.unit * length; i++) { |
162 |
| - for (var c = 0; c < options.channels; c++) { |
163 |
| - data.push(pack('v', 0)); samples++; |
164 |
| - } |
165 |
| - } |
166 |
| - }; |
| 146 | + var options = getOptions(opts), morse = encode(text, opts), |
| 147 | + AudioContext = window.AudioContext || window.webkitAudioContext, ctx = new AudioContext(), |
| 148 | + t = ctx.currentTime, oscillator = ctx.createOscillator(), gainNode = ctx.createGain(); |
| 149 | + |
| 150 | + oscillator.type = options.oscillator.type; |
| 151 | + oscillator.frequency.value = options.oscillator.frequency; |
| 152 | + oscillator.onended = options.oscillator.onended; |
| 153 | + |
| 154 | + gainNode.gain.setValueAtTime(0, t); |
| 155 | + |
| 156 | + var tone = function (i) { |
| 157 | + gainNode.gain.setValueAtTime(1, t); |
| 158 | + t += i * options.unit; |
| 159 | + }, silence = function (i) { |
| 160 | + gainNode.gain.setValueAtTime(0, t); |
| 161 | + t += i * options.unit; |
| 162 | + }; |
167 | 163 |
|
168 | 164 | for (var i = 0; i <= morse.length; i++) {
|
169 | 165 | if (morse[i] === options.space) {
|
|
179 | 175 | }
|
180 | 176 | }
|
181 | 177 |
|
182 |
| - var chunk1 = [ |
183 |
| - 'fmt ', |
184 |
| - pack('V', 16), |
185 |
| - pack('v', 1), |
186 |
| - pack('v', options.channels), |
187 |
| - pack('V', options.sampleRate), |
188 |
| - pack('V', options.sampleRate * options.channels * options.bitDepth / 8), |
189 |
| - pack('v', options.channels * options.bitDepth / 8), |
190 |
| - pack('v', options.bitDepth) |
191 |
| - ].join(''), |
192 |
| - chunk2 = [ |
193 |
| - 'data', |
194 |
| - pack('V', samples * options.channels * options.bitDepth / 8), |
195 |
| - data.join('') |
196 |
| - ].join(''), |
197 |
| - header = [ |
198 |
| - 'RIFF', |
199 |
| - pack('V', 4 + (8 + chunk1.length) + (8 + chunk2.length)), |
200 |
| - 'WAVE' |
201 |
| - ].join(''); |
| 178 | + oscillator.connect(gainNode); |
| 179 | + gainNode.connect(ctx.destination); |
202 | 180 |
|
203 |
| - if (typeof btoa === 'undefined') { |
204 |
| - global.btoa = function (str) { |
205 |
| - return new Buffer(str).toString('base64'); |
206 |
| - }; |
207 |
| - } |
208 |
| - |
209 |
| - return 'data:audio/wav;base64,' + encodeURI(btoa([header, chunk1, chunk2].join(''))); |
| 181 | + return { |
| 182 | + play: function () { |
| 183 | + oscillator.start(); |
| 184 | + oscillator.stop(t); |
| 185 | + }, |
| 186 | + stop: function () { |
| 187 | + oscillator.stop(); |
| 188 | + }, |
| 189 | + oscillator: oscillator |
| 190 | + }; |
210 | 191 | };
|
211 | 192 |
|
212 | 193 | return {
|
|
0 commit comments