diff --git a/README.md b/README.md
index 5501289..c983ddf 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
[![npm-version]][npm] [![npm-downloads]][npm] [![travis-ci]][travis]
Morse code encoder and decoder with no dependencies supports Latin, Cyrillic, Greek, Hebrew,
-Arabic, Persian, Japanese, and Korean characters with audio generation functionality.
+Arabic, Persian, Japanese, and Korean characters with audio generation functionality using the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API).
## Installation
@@ -24,9 +24,11 @@ $ yarn add morsify
```js
var morsify = require('morsify');
-morsify.encode('SOS'); // .../---/...
-morsify.decode('.../---/...'); // S O S
-morsify.audio('SOS'); // will return base64 encoded audio/wav data
+var encoded = morsify.encode('SOS'); // .../---/...
+var decoded = morsify.decode('.../---/...'); // S O S
+var audio = morsify.audio('SOS'), oscillator = audio.oscillator; // OscillatorNode
+audio.play(); // play audio
+audio.stop(); // stop audio
```
Or alternatively, you can also use the library directly with including the source file.
@@ -34,9 +36,11 @@ Or alternatively, you can also use the library directly with including the sourc
```html
```
@@ -52,7 +56,7 @@ Set the priority option according to the list below.
- 1 => ASCII (Default)
- 2 => Numbers
- 3 => Punctuation
-- 4 => Latin Extended (Turkish, Polski etc.)
+- 4 => Latin Extended (Turkish, Polish etc.)
- 5 => Cyrillic
- 6 => Greek
- 7 => Hebrew
@@ -62,18 +66,21 @@ Set the priority option according to the list below.
- 11 => Korean
```js
-morsify.encode('Ленинград', { priority: 5 }) // .-.././-./../-./--./.-./.-/-..
-morsify.decode('.../.-/--./.-/.--./.--', { priority: 6 }) // Σ Α Γ Α Π Ω
-morsify.decode('––– –... ––– –. ––. .. .–.. –––', { dash: '–', dot: '.', space: ' ', priority: 7 }) // ה ב ה נ ג י ל ה
-morsify.audio('البُراق', { // generates the morse .-/.-../-.../.-./.-/--.- then generates the audio from it
- channels: 1,
- sampleRate: 1012,
- bitDepth: 16,
- unit: 0.1,
- frequency: 440.0,
- volume: 32767,
- priority: 8
-})
+var cyrillic = morsify.encode('Ленинград', { priority: 5 }) // .-.././-./../-./--./.-./.-/-..
+var greek = morsify.decode('.../.-/--./.-/.--./.--', { priority: 6 }) // Σ Α Γ Α Π Ω
+var hebrew = morsify.decode('––– –... ––– –. ––. .. .–.. –––', { dash: '–', dot: '.', space: ' ', priority: 7 }) // ה ב ה נ ג י ל ה
+var arabicAudio = morsify.audio('البُراق', { // generates the morse .-/.-../-.../.-./.-/--.- then generates the audio from it
+ unit: 0.1, // period of one unit, in seconds, 1.2 / c where c is speed of transmission, in words per minute
+ oscillator: {
+ type: 'sine', // sine, square, sawtooth, triangle
+ frequency: 500, // value in hertz
+ onended: function () { // event that fires when the tone has stopped playing
+ console.log('ended');
+ },
+ }
+}), oscillator = arabicAudio.oscillator; // OscillatorNode
+arabicAudio.play(); // will start playing morse audio
+arabicAudio.stop(); // will stop playing morse audio
```
## Contributing and Known Issues
@@ -84,8 +91,6 @@ Currently, as a major drawback, Chinese characters are missing. Someone with the
[Chinese telegraph code](https://en.wikipedia.org/wiki/Chinese_telegraph_code) can help to implement it. Also someone who is proficient in Thai can help
to include [Thai alphabet](https://th.wikipedia.org/wiki/รหัสมอร์ส).
-On the other hand, audio generated by the script is playable in Firefox, however, Chrome support is currently missing.
-
## License
The MIT License (MIT). Please see [License File](LICENSE) for more information.
diff --git a/index.js b/index.js
index f31ceae..2c41292 100644
--- a/index.js
+++ b/index.js
@@ -36,7 +36,7 @@
'Ș': '1111', 'Š': '1111', 'Ŝ': '00010', 'ß': '000000', 'Þ': '01100', 'Ü': '0011',
'Ù': '0011', 'Ŭ': '0011', 'Ž': '11001', 'Ź': '110010', 'Ż': '11001'
},
- '5': { // Cyrilic Alphabet => https://en.wikipedia.org/wiki/Russian_Morse_code
+ '5': { // Cyrillic Alphabet => https://en.wikipedia.org/wiki/Russian_Morse_code
'А': '01', 'Б': '1000', 'В': '011', 'Г': '110', 'Д': '100', 'Е': '0',
'Ж': '0001', 'З': '1100', 'И': '00', 'Й': '0111', 'К': '101','Л': '0100',
'М': '11', 'Н': '10', 'О': '111', 'П': '0110', 'Р': '010', 'С': '000',
@@ -105,18 +105,19 @@
var getOptions = function (options) {
options = options || {};
+ options.oscillator = options.oscillator || {};
options = {
dash: options.dash || '-',
dot: options.dot || '.',
space: options.space || '/',
invalid: options.invalid || '#',
priority: options.priority || 1,
- channels: options.channels || 1,
- sampleRate: options.sampleRate || 1012,
- bitDepth: options.bitDepth || 16,
- unit: options.unit || 0.1,
- frequency: options.frequency || 440.0,
- volume: options.volume || 32767
+ unit: options.unit || 0.08, // period of one unit, in seconds, 1.2 / c where c is speed of transmission, in words per minute
+ oscillator: {
+ type: options.oscillator.type || 'sine', // sine, square, sawtooth, triangle
+ frequency: options.oscillator.frequency || 500, // value in hertz
+ onended: options.oscillator.onended || null, // event that fires when the tone has stopped playing
+ }
};
characters[0] = characters[options.priority];
return options;
@@ -141,29 +142,24 @@
}).join(' ').replace(/\s+/g, ' ');
};
- // Source: https://github.com/mattt/Morse.js
var audio = function (text, opts) {
- var options = getOptions(opts), morse = encode(text, opts), data = [], samples = 0,
- pack = function (e) {
- for (var b = '', c = 1, d = 0; d < e.length; d++) {
- var f = e.charAt(d), a = arguments[c++];
- b += f === 'v' ? String.fromCharCode(a & 255, a >> 8 & 255) : String.fromCharCode(a & 255, a >> 8 & 255, a >> 16 & 255, a >> 24 & 255);
- }
- return b;
- }, tone = function (length) {
- for (var i = 0; i < options.sampleRate * options.unit * length; i++) {
- for (var c = 0; c < options.channels; c++) {
- var v = options.volume * Math.sin((2 * Math.PI) * (i / options.sampleRate) * options.frequency);
- data.push(pack('v', v)); samples++;
- }
- }
- }, silence = function (length) {
- for (var i = 0; i < options.sampleRate * options.unit * length; i++) {
- for (var c = 0; c < options.channels; c++) {
- data.push(pack('v', 0)); samples++;
- }
- }
- };
+ var options = getOptions(opts), morse = encode(text, opts),
+ AudioContext = window.AudioContext || window.webkitAudioContext, ctx = new AudioContext(),
+ t = ctx.currentTime, oscillator = ctx.createOscillator(), gainNode = ctx.createGain();
+
+ oscillator.type = options.oscillator.type;
+ oscillator.frequency.value = options.oscillator.frequency;
+ oscillator.onended = options.oscillator.onended;
+
+ gainNode.gain.setValueAtTime(0, t);
+
+ var tone = function (i) {
+ gainNode.gain.setValueAtTime(1, t);
+ t += i * options.unit;
+ }, silence = function (i) {
+ gainNode.gain.setValueAtTime(0, t);
+ t += i * options.unit;
+ };
for (var i = 0; i <= morse.length; i++) {
if (morse[i] === options.space) {
@@ -179,34 +175,19 @@
}
}
- var chunk1 = [
- 'fmt ',
- pack('V', 16),
- pack('v', 1),
- pack('v', options.channels),
- pack('V', options.sampleRate),
- pack('V', options.sampleRate * options.channels * options.bitDepth / 8),
- pack('v', options.channels * options.bitDepth / 8),
- pack('v', options.bitDepth)
- ].join(''),
- chunk2 = [
- 'data',
- pack('V', samples * options.channels * options.bitDepth / 8),
- data.join('')
- ].join(''),
- header = [
- 'RIFF',
- pack('V', 4 + (8 + chunk1.length) + (8 + chunk2.length)),
- 'WAVE'
- ].join('');
+ oscillator.connect(gainNode);
+ gainNode.connect(ctx.destination);
- if (typeof btoa === 'undefined') {
- global.btoa = function (str) {
- return new Buffer(str).toString('base64');
- };
- }
-
- return 'data:audio/wav;base64,' + encodeURI(btoa([header, chunk1, chunk2].join('')));
+ return {
+ play: function () {
+ oscillator.start();
+ oscillator.stop(t);
+ },
+ stop: function () {
+ oscillator.stop();
+ },
+ oscillator: oscillator
+ };
};
return {
diff --git a/package.json b/package.json
index 270702e..846a283 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "morsify",
- "version": "0.1.0",
+ "version": "0.2.0",
"description": "Encodes and decodes morse code, creates morse code audio from text.",
"keywords": [
"morse",
diff --git a/test/index.js b/test/index.js
index 92be527..dd747be 100644
--- a/test/index.js
+++ b/test/index.js
@@ -158,8 +158,4 @@ describe('morsify', function () {
t.equal(morsify.decode('---/.---/./../-/...', options), 'ㅍ ㅎ ㅏ ㅑ ㅓ ㅕ');
t.equal(morsify.decode('.-/-./..../.-./-../..-', options), 'ㅗ ㅛ ㅜ ㅠ ㅡ ㅣ');
});
- it('creates audio', function () {
- t.equal('data:audio/wav;base64', morsify.audio('SOS').substr(0, 21));
- t.equal('UklGRsK8IAAAV0FWRWZtdCAQAAAAAQABAMO0AwAAw6gHAAACABAAZGF0YcKIIAAAAADDvjJ1wqLCm3hOwoDCpXE6wq/CiCJtEX/CvcKRaMKvwoJRfW/Cl8KBQsKTw654w53DhlBbwo7Csn9lwofCi10Cw40AAMO+MnXCosKbeE7CgMKlcTrCr8KIIm0Rf8K9wpFowq/CglF9b8KXwoFCwpPDrnjDncOGUFvCjsKyf2XCh8KLXQLDjQAAw74ydcKiwpt4TsKAwqVxOsKvwogibRF/wr3CkWjCr8KCUX1vwpfCgULCk8OueMOdw4ZQW8KOwrJ/ZcKHwotdAsONAADDvjJ1wqLCm3hOwoDCpXE6wq/CiCJtEX/CvcKRaMKvwoJRfW/Cl8KBQsKTw654w53DhlBbwo7Csn9lwofCi10Cw40AAMO+MnXCosKbeE7CgMKlcTrCr8KIIm0Rf8K', morsify.audio('SOS').substr(22, 463));
- });
});