<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kalana Wanniarachchi</title>
    <description>The latest articles on DEV Community by Kalana Wanniarachchi (@kalana_wanniarachchi_3ca4).</description>
    <link>https://dev.to/kalana_wanniarachchi_3ca4</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4058269%2F3524e76c-3ab2-4a05-9dc2-d4d701c03c0a.jpg</url>
      <title>DEV Community: Kalana Wanniarachchi</title>
      <link>https://dev.to/kalana_wanniarachchi_3ca4</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kalana_wanniarachchi_3ca4"/>
    <language>en</language>
    <item>
      <title>How Browser-Based Morse Audio Decoding Works: From Beeps to Text</title>
      <dc:creator>Kalana Wanniarachchi</dc:creator>
      <pubDate>Wed, 19 Aug 2026 12:02:40 +0000</pubDate>
      <link>https://dev.to/kalana_wanniarachchi_3ca4/how-browser-based-morse-audio-decoding-works-from-beeps-to-text-474n</link>
      <guid>https://dev.to/kalana_wanniarachchi_3ca4/how-browser-based-morse-audio-decoding-works-from-beeps-to-text-474n</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4uqg7t9w34svko3ab7ll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4uqg7t9w34svko3ab7ll.png" alt=" " width="505" height="554"&gt;&lt;/a&gt;Converting written Morse code into text is relatively straightforward.&lt;/p&gt;

&lt;p&gt;If the input is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... --- ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;a program can simply split the symbols and map them to letters.&lt;/p&gt;

&lt;p&gt;But decoding Morse code from an &lt;strong&gt;audio recording&lt;/strong&gt; is a very different problem.&lt;/p&gt;

&lt;p&gt;The browser does not receive dots and dashes.&lt;/p&gt;

&lt;p&gt;It receives a waveform containing frequencies, noise, silence, timing variations, and sometimes imperfect recordings.&lt;/p&gt;

&lt;p&gt;So how can a browser turn that audio into readable text?&lt;/p&gt;

&lt;p&gt;Here is a simplified look at the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Get the Audio Into the Browser
&lt;/h2&gt;

&lt;p&gt;The first step is obtaining an audio signal.&lt;/p&gt;

&lt;p&gt;There are two common sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An uploaded audio file&lt;/li&gt;
&lt;li&gt;Live microphone input&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern browsers provide APIs that make both possible without requiring desktop software.&lt;/p&gt;

&lt;p&gt;Once the audio is available, it can be represented as a stream of samples that can be analyzed over time.&lt;/p&gt;

&lt;p&gt;The important point is that at this stage the application still does not know anything about Morse code.&lt;/p&gt;

&lt;p&gt;It only has audio.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Find the Morse Tone
&lt;/h2&gt;

&lt;p&gt;A Morse recording may contain more than the signal we want.&lt;/p&gt;

&lt;p&gt;There might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;background hiss&lt;/li&gt;
&lt;li&gt;voices&lt;/li&gt;
&lt;li&gt;electrical hum&lt;/li&gt;
&lt;li&gt;room noise&lt;/li&gt;
&lt;li&gt;recording artifacts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The decoder therefore needs to identify the frequency region containing the Morse tone.&lt;/p&gt;

&lt;p&gt;A bandpass filter can help reduce energy outside the frequency range of interest.&lt;/p&gt;

&lt;p&gt;Instead of analyzing every sound equally, the decoder concentrates on the part of the spectrum where the signal is expected.&lt;/p&gt;

&lt;p&gt;This makes the next stage much more reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Decide When the Tone Is On or Off
&lt;/h2&gt;

&lt;p&gt;Once the useful frequency range has been isolated, the application needs to answer a simple question repeatedly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is the Morse tone currently present?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This sounds easy, but audio levels constantly fluctuate.&lt;/p&gt;

&lt;p&gt;Using one fixed threshold can cause problems.&lt;/p&gt;

&lt;p&gt;A quiet signal might fall below it, while background noise might occasionally rise above it.&lt;/p&gt;

&lt;p&gt;A more useful approach is to estimate the noise level dynamically and adjust the detection threshold.&lt;/p&gt;

&lt;p&gt;Hysteresis can also help.&lt;/p&gt;

&lt;p&gt;Instead of using exactly the same level to switch both ON and OFF, separate thresholds can reduce rapid false switching when the signal is close to the boundary.&lt;/p&gt;

&lt;p&gt;The result is a cleaner sequence such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ON
OFF
ON
OFF
ON
OFF
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the problem is no longer primarily about audio.&lt;/p&gt;

&lt;p&gt;It has become a timing problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Measure Tone Duration
&lt;/h2&gt;

&lt;p&gt;In International Morse code, timing determines whether a signal represents a dot or a dash.&lt;/p&gt;

&lt;p&gt;A dot is the basic timing unit.&lt;/p&gt;

&lt;p&gt;A dash lasts roughly three dot units.&lt;/p&gt;

&lt;p&gt;So after detecting a tone, the decoder measures how long that tone remained active.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;short tone  -&amp;gt; dot
long tone   -&amp;gt; dash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;short short short
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which represents the letter &lt;strong&gt;S&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;long long long
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which represents &lt;strong&gt;O&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But tone duration is only half of the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Silence Contains Information Too
&lt;/h2&gt;

&lt;p&gt;The gaps between signals are just as important as the beeps.&lt;/p&gt;

&lt;p&gt;Different silence durations separate different parts of the message.&lt;/p&gt;

&lt;p&gt;A short gap occurs between elements of the same character.&lt;/p&gt;

&lt;p&gt;A longer gap separates letters.&lt;/p&gt;

&lt;p&gt;An even longer gap separates words.&lt;/p&gt;

&lt;p&gt;So the decoder also measures every OFF period.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;short silence   -&amp;gt; same character
medium silence  -&amp;gt; next character
long silence    -&amp;gt; next word
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this step, a stream of perfectly detected dots and dashes could still be impossible to divide into meaningful text.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Estimate the Sender's Speed
&lt;/h2&gt;

&lt;p&gt;Real recordings are rarely produced at exactly the same speed.&lt;/p&gt;

&lt;p&gt;One sender might transmit slowly while another sends much faster.&lt;/p&gt;

&lt;p&gt;That means a decoder should avoid assuming that every dot has one fixed duration such as 100 milliseconds.&lt;/p&gt;

&lt;p&gt;A better approach is to examine the timing of the detected signal and estimate the basic timing unit.&lt;/p&gt;

&lt;p&gt;From that estimate, the decoder can classify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dots&lt;/li&gt;
&lt;li&gt;dashes&lt;/li&gt;
&lt;li&gt;character gaps&lt;/li&gt;
&lt;li&gt;word gaps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This also makes it possible to estimate the approximate sending speed in words per minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Convert the Detected Pattern Into Characters
&lt;/h2&gt;

&lt;p&gt;Once the signal has been converted into dots, dashes, and spacing, the final stage becomes much easier.&lt;/p&gt;

&lt;p&gt;The decoder can build patterns such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
---
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and look them up in an International Morse Code mapping.&lt;/p&gt;

&lt;p&gt;That produces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SOS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete pipeline therefore looks something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Audio
  ↓
Frequency filtering
  ↓
Tone detection
  ↓
Timing measurement
  ↓
Dot / dash classification
  ↓
Character separation
  ↓
Morse lookup
  ↓
Text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Why Real Audio Is Harder Than Generated Audio
&lt;/h2&gt;

&lt;p&gt;Computer-generated Morse code usually has perfect timing and a clean tone.&lt;/p&gt;

&lt;p&gt;Real-world recordings do not.&lt;/p&gt;

&lt;p&gt;Possible problems include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;background noise&lt;/li&gt;
&lt;li&gt;changing volume&lt;/li&gt;
&lt;li&gt;weak signals&lt;/li&gt;
&lt;li&gt;clipping&lt;/li&gt;
&lt;li&gt;echoes&lt;/li&gt;
&lt;li&gt;inconsistent keying&lt;/li&gt;
&lt;li&gt;multiple frequencies&lt;/li&gt;
&lt;li&gt;incorrect spacing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why decoding a typed string such as &lt;code&gt;... --- ...&lt;/code&gt; is much easier than decoding the same message from a noisy recording.&lt;/p&gt;

&lt;p&gt;Signal preprocessing and adaptive thresholds can make a large difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Experimenting With It in the Browser
&lt;/h2&gt;

&lt;p&gt;I built a free &lt;strong&gt;&lt;a href="https://morsecodecreator.org/tools/audio-decoder" rel="noopener noreferrer"&gt;Audio Morse Code Decoder&lt;/a&gt;&lt;/strong&gt; to experiment with this process directly in the browser.&lt;/p&gt;

&lt;p&gt;It can work with uploaded Morse recordings or live microphone input and converts detected signals into Morse code and readable text.&lt;/p&gt;

&lt;p&gt;The interesting part for me was that what initially looks like a simple “beeps to letters” problem quickly becomes a combination of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web Audio&lt;/li&gt;
&lt;li&gt;frequency filtering&lt;/li&gt;
&lt;li&gt;threshold detection&lt;/li&gt;
&lt;li&gt;timing analysis&lt;/li&gt;
&lt;li&gt;pattern recognition&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is a nice example of how browser APIs can be used for more than conventional UI work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Audio Morse decoding is a good reminder that the difficult part of a software problem is often not the final mapping step.&lt;/p&gt;

&lt;p&gt;Mapping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;... -&amp;gt; S
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is easy.&lt;/p&gt;

&lt;p&gt;Determining that a noisy waveform actually contained three correctly spaced short tones is the interesting part.&lt;/p&gt;

&lt;p&gt;Once the audio has been reduced to reliable timing events, the Morse translation itself becomes relatively simple.&lt;/p&gt;

&lt;p&gt;For developers interested in Web Audio or small signal-processing projects, Morse code is a surprisingly useful system to experiment with because its rules are simple enough to understand while the real-world audio introduces plenty of interesting engineering problems.&lt;/p&gt;

</description>
      <category>morse</category>
      <category>webdev</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How Web Audio API Powers Real-Time Morse Code Audio Decoding in Modern Browsers</title>
      <dc:creator>Kalana Wanniarachchi</dc:creator>
      <pubDate>Sat, 01 Aug 2026 17:16:35 +0000</pubDate>
      <link>https://dev.to/kalana_wanniarachchi_3ca4/how-web-audio-api-powers-real-time-morse-code-audio-decoding-in-modern-browsers-2adf</link>
      <guid>https://dev.to/kalana_wanniarachchi_3ca4/how-web-audio-api-powers-real-time-morse-code-audio-decoding-in-modern-browsers-2adf</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdrovv86v7xs0823fnnyd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdrovv86v7xs0823fnnyd.png" alt=" " width="800" height="642"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fugmy55cjxht33bopouff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fugmy55cjxht33bopouff.png" alt=" " width="798" height="208"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxo6ikuc3dg64dco6d497.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxo6ikuc3dg64dco6d497.png" alt=" " width="526" height="590"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7as84temj2l1mu4zpvoq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7as84temj2l1mu4zpvoq.png" alt=" " width="728" height="872"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3sd2ps5ieb7kzl7tzyey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3sd2ps5ieb7kzl7tzyey.png" alt=" " width="800" height="737"&gt;&lt;/a&gt;&lt;br&gt;
Most traditional online Morse code tools suffer from outdated user interfaces, slow server-side processing, or lack real-time audio playback. When building a modern Morse utility suite, leveraging the browser's native Web Audio API changes the game.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Architecture &amp;amp; Features
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client-Side Audio Synthesis:&lt;/strong&gt; Instead of loading external MP3/WAV sound files for Dit/Dah sound effects, we synthesize custom sine-wave audio oscillators directly in the browser using the Web Audio API. This ensures zero latency and crystal-clear sound at any WPM (Words Per Minute) speed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interactive Audio Practice Trainer:&lt;/strong&gt;&lt;br&gt;
To help users learn Morse code by ear (rather than memorizing visual dots and dashes), we built a sound-recognition quiz module that generates dynamic audio beeps and validates real-time user input.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Custom Secret Emoji Ciphers:&lt;/strong&gt;&lt;br&gt;
An algorithm that translates standard Morse code into custom emoji patterns, enabling users to send fun encrypted messages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Web Audio Signal Decoder:&lt;/strong&gt;&lt;br&gt;
Using frequency analysis and peak detection, the audio decoder processes incoming sound signals to automatically translate Morse audio back into readable text.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Try the Live Tool &amp;amp; Audio Decoder
&lt;/h3&gt;

&lt;p&gt;If you are interested in exploring the live application or testing out the interactive trainer and audio decoder, check out the project here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://www.morsecodecreator.org" rel="noopener noreferrer"&gt;Morse Code Creator &amp;amp; Audio Decoder Suite&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What are your thoughts on handling client-side audio synthesis in Next.js applications? Let me know in the comments below!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>morse</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
