@ozdemirburak/morse-code-translator 5.0.2 → 5.0.4

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.
@@ -1 +1 @@
1
- "use strict";const e={1:{A:"01",B:"1000",C:"1010",D:"100",E:"0",F:"0010",G:"110",H:"0000",I:"00",J:"0111",K:"101",L:"0100",M:"11",N:"10",O:"111",P:"0110",Q:"1101",R:"010",S:"000",T:"1",U:"001",V:"0001",W:"011",X:"1001",Y:"1011",Z:"1100"},2:{0:"11111",1:"01111",2:"00111",3:"00011",4:"00001",5:"00000",6:"10000",7:"11000",8:"11100",9:"11110"},3:{".":"010101",",":"110011","?":"001100","'":"011110","!":"101011","/":"10010","(":"10110",")":"101101","&":"01000",":":"111000",";":"101010","=":"10001","+":"01010","-":"100001",_:"001101",'"':"010010",$:"0001001","@":"011010","¿":"00101","¡":"110001"},4:{"Ã":"01101","Á":"01101","Å":"01101","À":"01101","Â":"01101","Ä":"0101","Ą":"0101","Æ":"0101","Ç":"10100","Ć":"10100","Ĉ":"10100","Č":"110","Ð":"00110","È":"01001","Ę":"00100","Ë":"00100","É":"00100","Ê":"10010","Ğ":"11010","Ĝ":"11010","Ĥ":"1111","İ":"01001","Ï":"10011","Ì":"01110","Ĵ":"01110","Ł":"01001","Ń":"11011","Ñ":"11011","Ó":"1110","Ò":"1110","Ö":"1110","Ô":"1110","Ø":"1110","Ś":"0001000","Ş":"01100","Ș":"1111","Š":"1111","Ŝ":"00010","ß":"000000","Þ":"01100","Ü":"0011","Ù":"0011","Ŭ":"0011","Ž":"11001","Ź":"110010","Ż":"11001"},5:{"А":"01","Б":"1000","В":"011","Г":"110","Д":"100","Е":"0","Ж":"0001","З":"1100","И":"00","Й":"0111","К":"101","Л":"0100","М":"11","Н":"10","О":"111","П":"0110","Р":"010","С":"000","Т":"1","У":"001","Ф":"0010","Х":"0000","Ц":"1010","Ч":"1110","Ш":"1111","Щ":"1101","Ъ":"11011","Ы":"1011","Ь":"1001","Э":"00100","Ю":"0011","Я":"0101","Ї":"01110","Є":"00100","І":"00","Ґ":"110"},6:{"Α":"01","Β":"1000","Γ":"110","Δ":"100","Ε":"0","Ζ":"1100","Η":"0000","Θ":"1010","Ι":"00","Κ":"101","Λ":"0100","Μ":"11","Ν":"10","Ξ":"1001","Ο":"111","Π":"0110","Ρ":"010","Σ":"000","Τ":"1","Υ":"1011","Φ":"0010","Χ":"1111","Ψ":"1101","Ω":"011"},7:{"א":"01","ב":"1000","ג":"110","ד":"100","ה":"111","ו":"0","ז":"1100","ח":"0000","ט":"001","י":"00","כ":"101","ל":"0100","מ":"11","נ":"10","ס":"1010","ע":"0111","פ":"0110","צ":"011","ק":"1101","ר":"010","ש":"000","ת":"1"},8:{"ا":"01","ب":"1000","ت":"1","ث":"1010","ج":"0111","ح":"0000","خ":"111","د":"100","ذ":"1100","ر":"010","ز":"1110","س":"000","ش":"1111","ص":"1001","ض":"0001","ط":"001","ظ":"1011","ع":"0101","غ":"110","ف":"0010","ق":"1101","ك":"101","ل":"0100","م":"11","ن":"10","ه":"00100","و":"011","ي":"00","ﺀ":"0"},9:{"ا":"01","ب":"1000","پ":"0110","ت":"1","ث":"1010","ج":"0111","چ":"1110","ح":"0000","خ":"1001","د":"100","ذ":"0001","ر":"010","ز":"1100","ژ":"110","س":"000","ش":"1111","ص":"0101","ض":"00100","ط":"001","ظ":"1011","ع":"111","غ":"0011","ف":"0010","ق":"111000","ک":"101","گ":"1101","ل":"0100","م":"11","ن":"10","و":"011","ه":"0","ی":"00"},10:{"ア":"11011","カ":"0100","サ":"10101","タ":"10","ナ":"010","ハ":"1000","マ":"1001","ヤ":"011","ラ":"000","ワ":"101","イ":"01","キ":"10100","シ":"11010","チ":"0010","ニ":"1010","ヒ":"11001","ミ":"00101","リ":"110","ヰ":"01001","ウ":"001","ク":"0001","ス":"11101","ツ":"0110","ヌ":"0000","フ":"1100","ム":"1","ユ":"10011","ル":"10110","ン":"01010","エ":"10111","ケ":"1011","セ":"01110","テ":"01011","ネ":"1101","ヘ":"0","メ":"10001","レ":"111","ヱ":"01100","オ":"01000","コ":"1111","ソ":"1110","ト":"00100","ノ":"0011","ホ":"100","モ":"10010","ヨ":"11","ロ":"0101","ヲ":"0111","゛":"00","゜":"00110","。":"010100","ー":"01101","、":"010101","(":"101101",")":"010010"},11:{"ㄱ":"0100","ㄴ":"0010","ㄷ":"1000","ㄹ":"0001","ㅁ":"11","ㅂ":"011","ㅅ":"110","ㅇ":"101","ㅈ":"0110","ㅊ":"1010","ㅋ":"1001","ㅌ":"1100","ㅍ":"111","ㅎ":"0111","ㅏ":"0","ㅑ":"00","ㅓ":"1","ㅕ":"000","ㅗ":"01","ㅛ":"10","ㅜ":"0000","ㅠ":"010","ㅡ":"100","ㅣ":"001"},12:{"ก":"110","ข":"1010","ค":"101","ง":"10110","จ":"10010","ฉ":"1111","ช":"1001","ซ":"1100","ญ":"0111","ด":"100","ต":"1","ถ":"10100","ท":"10011","น":"10","บ":"1000","ป":"0110","ผ":"1101","ฝ":"10101","พ":"01100","ฟ":"0010","ม":"11","ย":"1011","ร":"010","ล":"0100","ว":"011","ส":"000","ห":"0000","อ":"10001","ฮ":"11011","ฤ":"01011","ะ":"01000","า":"01","ิ":"00100","ี":"00","ึ":"00110","ื":"0011","ุ":"00101","ู":"1110","เ":"0","แ":"0101","ไ":"01001","โ":"111","ำ":"00010","่":"001","้":"0001","๊":"11000","๋":"01010","ั":"01101","็":"11100","์":"11001","ๆ":"10111","ฯ":"11010"}},t=t=>Object.assign(Object.assign({},e),{0:e[t.priority],1:Object.assign(Object.assign({},e[1]),{[t.separator]:t.space})}),n=(e,n)=>{const o={},r=t(e);for(const t in r){o[t]={};for(const n in r[t])o[t][n]=r[t][n].replace(/0/g,e.dot).replace(/1/g,e.dash)}return n||delete o[0],o},o=(e={})=>{var t,n,o;return Object.assign(Object.assign({},e),{dash:e.dash||"-",dot:e.dot||".",space:e.space||"/",separator:e.separator||" ",invalid:e.invalid||"#",priority:e.priority||1,wpm:e.wpm,unit:e.unit||.08,fwUnit:e.fwUnit||e.unit||.08,volume:e.volume||100,oscillator:Object.assign(Object.assign({},e.oscillator),{type:(null===(t=e.oscillator)||void 0===t?void 0:t.type)||"sine",frequency:(null===(n=e.oscillator)||void 0===n?void 0:n.frequency)||500,onended:(null===(o=e.oscillator)||void 0===o?void 0:o.onended)||null})})},r=(e,t)=>{let n,o=null,r=null,i=null,a=null;const[s,c]=((e,t,n=0)=>{const o=[];let{unit:r,fwUnit:i}=t,a=0;t.wpm&&(r=i=60/(50*t.wpm)),o.push([0,a]);const s=e=>{o.push([t.volume/100*1,n+a]),a+=e*r},c=e=>{o.push([0,n+a]),a+=e*r},l=e=>{o.push([0,n+a]),a+=e*i};for(let n=0,o=!1;n<=e.length;n++)e[n]===t.space?(l(7),o=!1):e[n]===t.dot?(o?c(1):o=!0,s(1)):e[n]===t.dash?(o?c(1):o=!0,s(3)):void 0!==e[n+1]&&e[n+1]!==t.space&&void 0!==e[n-1]&&e[n-1]!==t.space&&(l(3),o=!1);return[o,a]})(e,t);if(null===o&&"undefined"!=typeof window&&(o=window.AudioContext||window.webkitAudioContext,i=new o),null===r&&"undefined"!=typeof window&&(r=window.OfflineAudioContext||window.webkitOfflineAudioContext,a=new r(1,44100*c,44100)),!i||!a)throw new Error("Web Audio API is not supported in this browser");n=i.createBufferSource(),n.connect(i.destination);const l=a.createOscillator(),d=a.createGain();l.type=t.oscillator.type,l.frequency.value=t.oscillator.frequency,s.forEach((([e,t])=>d.gain.setValueAtTime(e,t))),l.connect(d),d.connect(a.destination),n.onended=t.oscillator.onended;const u=new Promise((e=>{l.start(0),a.startRendering(),a.oncomplete=t=>{n.buffer=t.renderedBuffer,e()}}));let p;const f=()=>{clearTimeout(p),p=0,n.stop(0)},w=async()=>{await u;const e=((e,t)=>{const n=new ArrayBuffer(44+2*t.length),o=new DataView(n),r=(e,t,n)=>{for(let o=0;o<n.length;o++)e.setUint8(t+o,n.charCodeAt(o))};return r(o,0,"RIFF"),o.setUint32(4,36+2*t.length,!0),r(o,8,"WAVE"),r(o,12,"fmt "),o.setUint32(16,16,!0),o.setUint16(20,1,!0),o.setUint16(22,1,!0),o.setUint32(24,e,!0),o.setUint32(28,4*e,!0),o.setUint16(32,2,!0),o.setUint16(34,16,!0),r(o,36,"data"),o.setUint32(40,2*t.length,!0),((e,t,n)=>{for(let o=0;o<n.length;o++,t+=2){const r=Math.max(-1,Math.min(1,n[o]));e.setInt16(t,r<0?32768*r:32767*r,!0)}})(o,44,t),o})(a.sampleRate,n.buffer.getChannelData(0));return new Blob([e],{type:"audio/wav"})},g=async()=>{const e=await w();return URL.createObjectURL(e)};return{play:async()=>{await u,n.start(i.currentTime),p=setTimeout((()=>{f()}),1e3*c)},stop:f,getWaveBlob:w,getWaveUrl:g,exportWave:async e=>{const t=await g(),n=document.createElement("a");n.href=t,n.target="_blank",n.download=e||"morse.wav",n.click()},context:i,oscillator:l,gainNode:d}};var i,a;i=globalThis,a=()=>{const e=(e,n)=>{const r=o(n),i=t(r);return[...e.replace(/\s+/g,r.separator).trim().toLocaleUpperCase()].map((function(e){for(const t in i)if(void 0!==i[t]&&void 0!==i[t][e])return i[t][e];return r.invalid})).join(r.separator).replace(/0/g,r.dot).replace(/1/g,r.dash)};return{characters:(e,t)=>n(o(e),t),decode:(e,t)=>{const r=o(t),i=(e=>{const t={},o=n(e,!0);for(const e in o)for(const n in o[e])void 0===t[o[e][n]]&&(t[o[e][n]]=n);return t})(r);return e.replace(/\s+/g,r.separator).trim().split(r.separator).map((function(e){return void 0!==i[e]?i[e]:r.invalid})).join("")},encode:e,audio:(t,n,i)=>{const a=i||e(t,n),s=o(n);return r(a,s)}}},"object"==typeof exports?module.exports=a():"function"==typeof define&&define.amd?define(a):void 0!==i&&(i["morse-code-translator"]=a());
1
+ "use strict";const e={1:{A:"01",B:"1000",C:"1010",D:"100",E:"0",F:"0010",G:"110",H:"0000",I:"00",J:"0111",K:"101",L:"0100",M:"11",N:"10",O:"111",P:"0110",Q:"1101",R:"010",S:"000",T:"1",U:"001",V:"0001",W:"011",X:"1001",Y:"1011",Z:"1100"},2:{0:"11111",1:"01111",2:"00111",3:"00011",4:"00001",5:"00000",6:"10000",7:"11000",8:"11100",9:"11110"},3:{".":"010101",",":"110011","?":"001100","'":"011110","!":"101011","/":"10010","(":"10110",")":"101101","&":"01000",":":"111000",";":"101010","=":"10001","+":"01010","-":"100001",_:"001101",'"':"010010",$:"0001001","@":"011010","¿":"00101","¡":"110001"},4:{"Ã":"01101","Á":"01101","Å":"01101","À":"01101","Â":"01101","Ä":"0101","Ą":"0101","Æ":"0101","Ç":"10100","Ć":"10100","Ĉ":"10100","Č":"110","Ð":"00110","È":"01001","Ę":"00100","Ë":"00100","É":"00100","Ê":"10010","Ğ":"11010","Ĝ":"11010","Ĥ":"1111","İ":"01001","Ï":"10011","Ì":"01110","Ĵ":"01110","Ł":"01001","Ń":"11011","Ñ":"11011","Ó":"1110","Ò":"1110","Ö":"1110","Ô":"1110","Ø":"1110","Ś":"0001000","Ş":"01100","Ș":"1111","Š":"1111","Ŝ":"00010","ß":"000000","Þ":"01100","Ü":"0011","Ù":"0011","Ŭ":"0011","Ž":"11001","Ź":"110010","Ż":"11001"},5:{"А":"01","Б":"1000","В":"011","Г":"110","Д":"100","Е":"0","Ж":"0001","З":"1100","И":"00","Й":"0111","К":"101","Л":"0100","М":"11","Н":"10","О":"111","П":"0110","Р":"010","С":"000","Т":"1","У":"001","Ф":"0010","Х":"0000","Ц":"1010","Ч":"1110","Ш":"1111","Щ":"1101","Ъ":"11011","Ы":"1011","Ь":"1001","Э":"00100","Ю":"0011","Я":"0101","Ї":"01110","Є":"00100","І":"00","Ґ":"110"},6:{"Α":"01","Β":"1000","Γ":"110","Δ":"100","Ε":"0","Ζ":"1100","Η":"0000","Θ":"1010","Ι":"00","Κ":"101","Λ":"0100","Μ":"11","Ν":"10","Ξ":"1001","Ο":"111","Π":"0110","Ρ":"010","Σ":"000","Τ":"1","Υ":"1011","Φ":"0010","Χ":"1111","Ψ":"1101","Ω":"011"},7:{"א":"01","ב":"1000","ג":"110","ד":"100","ה":"111","ו":"0","ז":"1100","ח":"0000","ט":"001","י":"00","כ":"101","ל":"0100","מ":"11","נ":"10","ס":"1010","ע":"0111","פ":"0110","צ":"011","ק":"1101","ר":"010","ש":"000","ת":"1"},8:{"ا":"01","ب":"1000","ت":"1","ث":"1010","ج":"0111","ح":"0000","خ":"111","د":"100","ذ":"1100","ر":"010","ز":"1110","س":"000","ش":"1111","ص":"1001","ض":"0001","ط":"001","ظ":"1011","ع":"0101","غ":"110","ف":"0010","ق":"1101","ك":"101","ل":"0100","م":"11","ن":"10","ه":"00100","و":"011","ي":"00","ﺀ":"0"},9:{"ا":"01","ب":"1000","پ":"0110","ت":"1","ث":"1010","ج":"0111","چ":"1110","ح":"0000","خ":"1001","د":"100","ذ":"0001","ر":"010","ز":"1100","ژ":"110","س":"000","ش":"1111","ص":"0101","ض":"00100","ط":"001","ظ":"1011","ع":"111","غ":"0011","ف":"0010","ق":"111000","ک":"101","گ":"1101","ل":"0100","م":"11","ن":"10","و":"011","ه":"0","ی":"00"},10:{"ア":"11011","カ":"0100","サ":"10101","タ":"10","ナ":"010","ハ":"1000","マ":"1001","ヤ":"011","ラ":"000","ワ":"101","イ":"01","キ":"10100","シ":"11010","チ":"0010","ニ":"1010","ヒ":"11001","ミ":"00101","リ":"110","ヰ":"01001","ウ":"001","ク":"0001","ス":"11101","ツ":"0110","ヌ":"0000","フ":"1100","ム":"1","ユ":"10011","ル":"10110","ン":"01010","エ":"10111","ケ":"1011","セ":"01110","テ":"01011","ネ":"1101","ヘ":"0","メ":"10001","レ":"111","ヱ":"01100","オ":"01000","コ":"1111","ソ":"1110","ト":"00100","ノ":"0011","ホ":"100","モ":"10010","ヨ":"11","ロ":"0101","ヲ":"0111","゛":"00","゜":"00110","。":"010100","ー":"01101","、":"010101","(":"101101",")":"010010"},11:{"ㄱ":"0100","ㄴ":"0010","ㄷ":"1000","ㄹ":"0001","ㅁ":"11","ㅂ":"011","ㅅ":"110","ㅇ":"101","ㅈ":"0110","ㅊ":"1010","ㅋ":"1001","ㅌ":"1100","ㅍ":"111","ㅎ":"0111","ㅏ":"0","ㅑ":"00","ㅓ":"1","ㅕ":"000","ㅗ":"01","ㅛ":"10","ㅜ":"0000","ㅠ":"010","ㅡ":"100","ㅣ":"001","ㅐ":"1101","ㅔ":"1011"},12:{"ก":"110","ข":"1010","ค":"101","ง":"10110","จ":"10010","ฉ":"1111","ช":"1001","ซ":"1100","ญ":"0111","ด":"100","ต":"1","ถ":"10100","ท":"10011","น":"10","บ":"1000","ป":"0110","ผ":"1101","ฝ":"10101","พ":"01100","ฟ":"0010","ม":"11","ย":"1011","ร":"010","ล":"0100","ว":"011","ส":"000","ห":"0000","อ":"10001","ฮ":"11011","ฤ":"01011","ะ":"01000","า":"01","ิ":"00100","ี":"00","ึ":"00110","ื":"0011","ุ":"00101","ู":"1110","เ":"0","แ":"0101","ไ":"01001","โ":"111","ำ":"00010","่":"001","้":"0001","๊":"11000","๋":"01010","ั":"01101","็":"11100","์":"11001","ๆ":"10111","ฯ":"11010"}},t=t=>Object.assign(Object.assign({},e),{0:e[t.priority],1:Object.assign(Object.assign({},e[1]),{[t.separator]:t.space})}),n=(e,n)=>{const o={},r=t(e);for(const t in r){o[t]={};for(const n in r[t])o[t][n]=r[t][n].replace(/0/g,e.dot).replace(/1/g,e.dash)}return n||delete o[0],o},o=(e={})=>{var t,n,o;return Object.assign(Object.assign({},e),{dash:e.dash||"-",dot:e.dot||".",space:e.space||"/",separator:e.separator||" ",invalid:e.invalid||"#",priority:e.priority||1,wpm:e.wpm,unit:e.unit||.08,fwUnit:e.fwUnit||e.unit||.08,volume:e.volume||100,oscillator:Object.assign(Object.assign({},e.oscillator),{type:(null===(t=e.oscillator)||void 0===t?void 0:t.type)||"sine",frequency:(null===(n=e.oscillator)||void 0===n?void 0:n.frequency)||500,onended:(null===(o=e.oscillator)||void 0===o?void 0:o.onended)||null})})},r=(e,t)=>{let n=window.AudioContext||window.webkitAudioContext,o=window.OfflineAudioContext||window.webkitOfflineAudioContext;if(!n||!o)throw new Error("Web Audio API is not supported in this browser");const r=new n,[a,i]=((e,t,n=0)=>{const o=[];let{unit:r,fwUnit:a}=t,i=0;t.wpm&&(r=a=60/(50*t.wpm)),o.push([0,i]);const s=e=>{o.push([t.volume/100*1,n+i]),i+=e*r},c=e=>{o.push([0,n+i]),i+=e*r},l=e=>{o.push([0,n+i]),i+=e*a};for(let n=0,o=!1;n<=e.length;n++)e[n]===t.space?(l(7),o=!1):e[n]===t.dot?(o?c(1):o=!0,s(1)):e[n]===t.dash?(o?c(1):o=!0,s(3)):void 0!==e[n+1]&&e[n+1]!==t.space&&void 0!==e[n-1]&&e[n-1]!==t.space&&(l(3),o=!1);return[o,i]})(e,t),s=new o(1,44100*i,44100),c=s.createOscillator(),l=s.createGain();let d;c.type=t.oscillator.type,c.frequency.value=t.oscillator.frequency,a.forEach((([e,t])=>l.gain.setValueAtTime(e,t))),c.connect(l),l.connect(s.destination);const u=new Promise(((e,n)=>{c.start(0),s.startRendering(),s.oncomplete=o=>{try{d=r.createBufferSource(),d.buffer=o.renderedBuffer,d.connect(r.destination),d.onended=t.oscillator.onended,e()}catch(e){n(e)}},s.onerror=e=>{n(e)}}));let p;const f=()=>{clearTimeout(p),d&&d.stop(0)},w=async()=>{await u;const e=((e,t)=>{const n=new ArrayBuffer(44+2*t.length),o=new DataView(n),r=(e,t,n)=>{for(let o=0;o<n.length;o++)e.setUint8(t+o,n.charCodeAt(o))};return r(o,0,"RIFF"),o.setUint32(4,36+2*t.length,!0),r(o,8,"WAVE"),r(o,12,"fmt "),o.setUint32(16,16,!0),o.setUint16(20,1,!0),o.setUint16(22,1,!0),o.setUint32(24,e,!0),o.setUint32(28,4*e,!0),o.setUint16(32,2,!0),o.setUint16(34,16,!0),r(o,36,"data"),o.setUint32(40,2*t.length,!0),((e,t,n)=>{for(let o=0;o<n.length;o++,t+=2){const r=Math.max(-1,Math.min(1,n[o]));e.setInt16(t,r<0?32768*r:32767*r,!0)}})(o,44,t),o})(s.sampleRate,d.buffer.getChannelData(0));return new Blob([e],{type:"audio/wav"})},g=async()=>{const e=await w();return URL.createObjectURL(e)};return{play:async()=>{await u,"suspended"===r.state&&await r.resume(),d.start(r.currentTime),p=window.setTimeout((()=>{f()}),1e3*i)},stop:f,getWaveBlob:w,getWaveUrl:g,exportWave:async e=>{const t=await g(),n=document.createElement("a");n.href=t,n.target="_blank",n.download=e||"morse.wav",n.click()},context:r,oscillator:c,gainNode:l}};var a,i;a=globalThis,i=()=>{const e=(e,n)=>{const r=o(n),a=t(r);return[...e.replace(/\s+/g,r.separator).trim().toLocaleUpperCase()].map((function(e){for(const t in a)if(void 0!==a[t]&&void 0!==a[t][e])return a[t][e];return r.invalid})).join(r.separator).replace(/0/g,r.dot).replace(/1/g,r.dash)};return{characters:(e,t)=>n(o(e),t),decode:(e,t)=>{const r=o(t),a=(e=>{const t={},o=n(e,!0);for(const e in o)for(const n in o[e])void 0===t[o[e][n]]&&(t[o[e][n]]=n);return t})(r);return e.replace(/\s+/g,r.separator).trim().split(r.separator).map((function(e){return void 0!==a[e]?a[e]:r.invalid})).join("")},encode:e,audio:(t,n,a)=>{const i=a||e(t,n),s=o(n);return r(i,s)}}},"object"==typeof exports?module.exports=i():"function"==typeof define&&define.amd?define(i):void 0!==a&&(a["morse-code-translator"]=i());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ozdemirburak/morse-code-translator",
3
- "version": "5.0.2",
3
+ "version": "5.0.4",
4
4
  "description": "Morse code translator helps you convert text to Morse code and vice versa, with the option to play Morse code audio.",
5
5
  "keywords": [
6
6
  "morse",
package/src/audio.ts CHANGED
@@ -94,37 +94,16 @@ const encodeWAV = (sampleRate: number, samples: Float32Array) => {
94
94
  };
95
95
 
96
96
  const audio = (morse: string, options: Options) => {
97
- let AudioContext: {
98
- new(contextOptions?: AudioContextOptions): AudioContext;
99
- prototype: AudioContext;
100
- } = null;
101
- let OfflineAudioContext: {
102
- new(contextOptions: OfflineAudioContextOptions): OfflineAudioContext;
103
- new(numberOfChannels: number, length: number, sampleRate: number): OfflineAudioContext;
104
- prototype: OfflineAudioContext;
105
- } = null;
106
- let context: AudioContext = null;
107
- let offlineContext: OfflineAudioContext = null;
108
- let source: AudioBufferSourceNode;
109
-
110
- const [gainValues, totalTime] = getGainTimings(morse, options);
111
-
112
- if (AudioContext === null && typeof window !== 'undefined') {
113
- AudioContext = window.AudioContext || (window as any).webkitAudioContext;
114
- context = new AudioContext();
115
- }
116
-
117
- if (OfflineAudioContext === null && typeof window !== 'undefined') {
118
- OfflineAudioContext = window.OfflineAudioContext || (window as any).webkitOfflineAudioContext;
119
- offlineContext = new OfflineAudioContext(1, 44100 * totalTime, 44100);
120
- }
97
+ let AudioContextClass = window.AudioContext || (window as any).webkitAudioContext;
98
+ let OfflineAudioContextClass = window.OfflineAudioContext || (window as any).webkitOfflineAudioContext;
121
99
 
122
- if (!context || !offlineContext) {
100
+ if (!AudioContextClass || !OfflineAudioContextClass) {
123
101
  throw new Error('Web Audio API is not supported in this browser');
124
102
  }
125
103
 
126
- source = context.createBufferSource();
127
- source.connect(context.destination);
104
+ const context = new AudioContextClass();
105
+ const [gainValues, totalTime] = getGainTimings(morse, options);
106
+ const offlineContext = new OfflineAudioContextClass(1, 44100 * totalTime, 44100);
128
107
 
129
108
  const oscillator = offlineContext.createOscillator();
130
109
  const gainNode = offlineContext.createGain();
@@ -136,15 +115,26 @@ const audio = (morse: string, options: Options) => {
136
115
 
137
116
  oscillator.connect(gainNode);
138
117
  gainNode.connect(offlineContext.destination);
139
- source.onended = options.oscillator.onended;
140
118
 
141
- // Inspired by: http://joesul.li/van/tale-of-no-clocks/
142
- const render = new Promise<void>(resolve => {
119
+ let source: AudioBufferSourceNode;
120
+
121
+ // Render the audio buffer
122
+ const render = new Promise<void>((resolve, reject) => {
143
123
  oscillator.start(0);
144
124
  offlineContext.startRendering();
145
125
  offlineContext.oncomplete = (e) => {
146
- source.buffer = e.renderedBuffer;
147
- resolve();
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);
148
138
  };
149
139
  });
150
140
 
@@ -152,20 +142,24 @@ const audio = (morse: string, options: Options) => {
152
142
 
153
143
  const play = async () => {
154
144
  await render;
145
+ if (context.state === 'suspended') {
146
+ await context.resume();
147
+ }
155
148
  source.start(context.currentTime);
156
- timeout = setTimeout(() => { stop() }, totalTime * 1000);
149
+ timeout = window.setTimeout(() => { stop(); }, totalTime * 1000);
157
150
  };
158
151
 
159
152
  const stop = () => {
160
153
  clearTimeout(timeout);
161
- timeout = 0;
162
- source.stop(0);
154
+ if (source) {
155
+ source.stop(0);
156
+ }
163
157
  };
164
158
 
165
159
  const getWaveBlob = async () => {
166
160
  await render;
167
161
  const waveData = encodeWAV(offlineContext.sampleRate, source.buffer.getChannelData(0));
168
- return new Blob([waveData], { 'type': 'audio/wav' });
162
+ return new Blob([waveData], { type: 'audio/wav' });
169
163
  };
170
164
 
171
165
  const getWaveUrl = async () => {
@@ -173,7 +167,7 @@ const audio = (morse: string, options: Options) => {
173
167
  return URL.createObjectURL(audioBlob);
174
168
  };
175
169
 
176
- const exportWave = async (filename) => {
170
+ const exportWave = async (filename: string) => {
177
171
  const waveUrl = await getWaveUrl();
178
172
  const anchor = document.createElement('a');
179
173
  anchor.href = waveUrl;
package/src/characters.ts CHANGED
@@ -73,11 +73,12 @@ const baseCharacters: Characters = {
73
73
  '゛': '00', '゜': '00110', '。': '010100', 'ー': '01101', '、': '010101',
74
74
  '(': '101101', ')': '010010'
75
75
  },
76
- '11': { // Korean Alphabet => https://en.wikipedia.org/wiki/SKATS
76
+ '11': { // Korean Alphabet => https://ko.wikipedia.org/wiki/%EB%AA%A8%EC%8A%A4_%EB%B6%80%ED%98%B8
77
77
  'ㄱ': '0100', 'ㄴ': '0010', 'ㄷ': '1000', 'ㄹ': '0001', 'ㅁ': '11', 'ㅂ': '011',
78
78
  'ㅅ': '110', 'ㅇ': '101', 'ㅈ': '0110', 'ㅊ': '1010', 'ㅋ': '1001', 'ㅌ': '1100',
79
79
  'ㅍ': '111', 'ㅎ': '0111', 'ㅏ': '0', 'ㅑ': '00', 'ㅓ': '1', 'ㅕ': '000',
80
- 'ㅗ': '01', 'ㅛ': '10', 'ㅜ': '0000', 'ㅠ': '010', 'ㅡ': '100', 'ㅣ': '001'
80
+ 'ㅗ': '01', 'ㅛ': '10', 'ㅜ': '0000', 'ㅠ': '010', 'ㅡ': '100', 'ㅣ': '001',
81
+ 'ㅐ': '1101', 'ㅔ': '1011'
81
82
  },
82
83
  '12': { // Thai Alphabet => https://th.wikipedia.org/wiki/รหัสมอร์ส
83
84
  'ก': '110', 'ข': '1010', 'ค': '101', 'ง': '10110', 'จ': '10010',
package/src/index.js CHANGED
@@ -79,7 +79,8 @@ const baseCharacters = {
79
79
  'ㄱ': '0100', 'ㄴ': '0010', 'ㄷ': '1000', 'ㄹ': '0001', 'ㅁ': '11', 'ㅂ': '011',
80
80
  'ㅅ': '110', 'ㅇ': '101', 'ㅈ': '0110', 'ㅊ': '1010', 'ㅋ': '1001', 'ㅌ': '1100',
81
81
  'ㅍ': '111', 'ㅎ': '0111', 'ㅏ': '0', 'ㅑ': '00', 'ㅓ': '1', 'ㅕ': '000',
82
- 'ㅗ': '01', 'ㅛ': '10', 'ㅜ': '0000', 'ㅠ': '010', 'ㅡ': '100', 'ㅣ': '001'
82
+ 'ㅗ': '01', 'ㅛ': '10', 'ㅜ': '0000', 'ㅠ': '010', 'ㅡ': '100', 'ㅣ': '001',
83
+ 'ㅐ': '1101', 'ㅔ': '1011'
83
84
  },
84
85
  '12': {
85
86
  'ก': '110', 'ข': '1010', 'ค': '101', 'ง': '10110', 'จ': '10010',
@@ -224,25 +225,14 @@ const encodeWAV = (sampleRate, samples) => {
224
225
  return view;
225
226
  };
226
227
  const audio = (morse, options) => {
227
- let AudioContext = null;
228
- let OfflineAudioContext = null;
229
- let context = null;
230
- let offlineContext = null;
231
- let source;
232
- const [gainValues, totalTime] = getGainTimings(morse, options);
233
- if (AudioContext === null && typeof window !== 'undefined') {
234
- AudioContext = window.AudioContext || window.webkitAudioContext;
235
- context = new AudioContext();
236
- }
237
- if (OfflineAudioContext === null && typeof window !== 'undefined') {
238
- OfflineAudioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext;
239
- offlineContext = new OfflineAudioContext(1, 44100 * totalTime, 44100);
240
- }
241
- if (!context || !offlineContext) {
228
+ let AudioContextClass = window.AudioContext || window.webkitAudioContext;
229
+ let OfflineAudioContextClass = window.OfflineAudioContext || window.webkitOfflineAudioContext;
230
+ if (!AudioContextClass || !OfflineAudioContextClass) {
242
231
  throw new Error('Web Audio API is not supported in this browser');
243
232
  }
244
- source = context.createBufferSource();
245
- source.connect(context.destination);
233
+ const context = new AudioContextClass();
234
+ const [gainValues, totalTime] = getGainTimings(morse, options);
235
+ const offlineContext = new OfflineAudioContextClass(1, 44100 * totalTime, 44100);
246
236
  const oscillator = offlineContext.createOscillator();
247
237
  const gainNode = offlineContext.createGain();
248
238
  oscillator.type = options.oscillator.type;
@@ -250,31 +240,46 @@ const audio = (morse, options) => {
250
240
  gainValues.forEach(([value, time]) => gainNode.gain.setValueAtTime(value, time));
251
241
  oscillator.connect(gainNode);
252
242
  gainNode.connect(offlineContext.destination);
253
- source.onended = options.oscillator.onended;
254
- // Inspired by: http://joesul.li/van/tale-of-no-clocks/
255
- const render = new Promise(resolve => {
243
+ let source;
244
+ // Render the audio buffer
245
+ const render = new Promise((resolve, reject) => {
256
246
  oscillator.start(0);
257
247
  offlineContext.startRendering();
258
248
  offlineContext.oncomplete = (e) => {
259
- source.buffer = e.renderedBuffer;
260
- resolve();
249
+ try {
250
+ source = context.createBufferSource();
251
+ source.buffer = e.renderedBuffer;
252
+ source.connect(context.destination);
253
+ source.onended = options.oscillator.onended;
254
+ resolve();
255
+ }
256
+ catch (err) {
257
+ reject(err);
258
+ }
259
+ };
260
+ offlineContext.onerror = (err) => {
261
+ reject(err);
261
262
  };
262
263
  });
263
264
  let timeout;
264
265
  const play = async () => {
265
266
  await render;
267
+ if (context.state === 'suspended') {
268
+ await context.resume();
269
+ }
266
270
  source.start(context.currentTime);
267
- timeout = setTimeout(() => { stop(); }, totalTime * 1000);
271
+ timeout = window.setTimeout(() => { stop(); }, totalTime * 1000);
268
272
  };
269
273
  const stop = () => {
270
274
  clearTimeout(timeout);
271
- timeout = 0;
272
- source.stop(0);
275
+ if (source) {
276
+ source.stop(0);
277
+ }
273
278
  };
274
279
  const getWaveBlob = async () => {
275
280
  await render;
276
281
  const waveData = encodeWAV(offlineContext.sampleRate, source.buffer.getChannelData(0));
277
- return new Blob([waveData], { 'type': 'audio/wav' });
282
+ return new Blob([waveData], { type: 'audio/wav' });
278
283
  };
279
284
  const getWaveUrl = async () => {
280
285
  const audioBlob = await getWaveBlob();