🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)
🔧 AI Nachrichten Major AI platforms go down in unprecedented simultaneous outage(03.09.2026 um 17:34 Uhr)
🔧 AI Nachrichten ChatGPT, Claude, and Grok Down? Users Report Widespread Outages(03.09.2026 um 19:14 Uhr)
🔧 AI Nachrichten OpenAI Launches GPT-6 Astra, Says We May Have Entered the AGI Era(03.09.2026 um 22:08 Uhr)
🔧 AI Nachrichten Claude Comes to CarPlay as Fifth Major AI Chatbot App(05.09.2026 um 05:31 Uhr)
🔧 AI Nachrichten OpenAI’s GPT-6 Astra Is AGI, Says NVIDIA CEO Jensen Huang(07.09.2026 um 06:31 Uhr)
🔧 AI Nachrichten Blame AI companies for Mac mini and Mac Studio shortage(31.08.2026 um 10:32 Uhr)

🔧 Programmierung 🕛 kürzlich 7 Min Lesezeit
0

I built a Morse code translator that renders WAV audio entirely in the browser

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

Every free Morse code translator I tried had at least one dealbreaker. Some had no audio at all. Some paywalled the playback. Some wouldn't let me set Farnsworth spacing. And none of them could export the audio as a WAV file without a server round-trip.



So I spent a weekend building one that fixes all four, and turned out to be a nice little engineering puzzle.



Live tool: if you want the whole story.



Once the timing rules are clear, the encoded Morse string is easy to schedule as audio.





The trick — unifying playback and WAV export



Here's the part I got wrong on the first pass. I wrote the realtime playback first, using a Web Audio API oscillator that scheduled tones on the audio graph. Worked great.



Then I added WAV export. I wrote it with an OfflineAudioContext + a separate scheduler. Worked... almost.



The exported WAV had subtle off-by-one gaps between letters that the browser preview didn't have. Different code paths, different timing bugs.



The fix was to unify the schedule generation into one function that both consumers read from:



js

function buildSchedule(pattern, timings) {

const events = [];

let t = 0.05; // small offset from t=0 so

for (let i = 0; i < pattern.length; i++) {

const ch = pattern[i];

const next = pattern[i + 1];

if (ch === '.' || ch === '-') {

const dur = ch === '.' ? timings.dit : timings.dah;

events.push({ t, dur });

t += dur;

// Only add intra-symbol gap if next c

// in the same letter. Space and slash

if (next === '.' || next === '-') t += timings.intra;

} else if (ch === ' ') {

t += timings.letter;

} else if (ch === '/') {

t += timings.word;

}

}

return { events, totalDur: t + 0.1 };

}



One schedule builder. Two consumers. Both realtime and offline reads the same list of {t, dur} events, so "play then download" produces the same audio down to the sample.





Scheduling a tone



Same helper for both paths:



js

function scheduleToneOn(ctx, t, dur, freq) {

const osc = ctx.createOscillator();

const gain = ctx.createGain();

osc.type = 'sine';

osc.frequency.value = freq;

const fade = Math.min(0.005, dur / 4);

gain.gain.setValueAtTime(0, t);

gain.gain.linearRampToValueAtTime(0.4, t + fade);

gain.gain.setValueAtTime(0.4, t + Math.max(dur - fade, fade));

gain.gain.linearRampToValueAtTime(0, t + d

osc.connect(gain).connect(ctx.destination);

osc.start(t);

osc.stop(t + dur + 0.02);

return osc;

}



The gain envelope with a 5 ms fade in/out maave at 600 Hz produces audible clicks at the

start and end of every dit. The linear ramp





PCM 16-bit LE WAV encoder



OfflineAudioContext gives you an AudioBufferg()`. To download it, encode as WAV manually —

no library needed, the RIFF header is small:




CODE
function encodeWav(audioBuffer) {
const numCh = 1;
const sampleRate = audioBuffer.sampleRate;
const samples = audioBuffer.getChannelData
const bytesPerSample = 2;
const blockAlign = numCh * bytesPerSample;
const byteRate = sampleRate * blockAlign;
const dataSize = samples.length * bytesPerSample;
const buffer = new ArrayBuffer(44 + dataSi
const view = new DataView(buffer);

writeString(view, 0, 'RIFF');
view.setUint32(4, 36 + dataSize, true);
writeString(view, 8, 'WAVE');
writeString(view, 12, 'fmt ');
view.setUint32(16, 16, true);
view.setUint16(20, 1, true); // PCM
view.setUint16(22, numCh, true);
view.setUint32(24, sampleRate, true);
view.setUint32(28, byteRate, true);
view.setUint16(32, blockAlign, true);
view.setUint16(34, 16, true);
writeString(view, 36, 'data');
view.setUint32(40, dataSize, true);

let off = 44;
for (let i = 0; i < samples.length; i++, off += 2) {
const s = Math.max(-1, Math.min(1, samples[i]));
view.setInt16(off, s < 0 ? s * 0x8000 : s * 0x7fff, true);
}
return buffer;
}






Wrap the returned ArrayBuffer in a Blob({ type: 'audio/wav' }), create an object URL, click a temporary anchor, and the browser saves the file. No server touched.






Farnsworth done as two sliders



Every free translator I saw either skipped F. Real training needs two knobs:





  • Character speed — how fast each letter sounds


  • Text speed — the effective gap between letters



Beginners drill 20 WPM characters with 8 WPMshapes, but enough thinking room. That's how

ARRL and every serious trainer teaches it. Tfor this, not one.



In code, this changes the letter/word gap unmbol dit unit at character speed:




CODE
const unit = 1.2 / wpm;                       // char speed
const gapUnit = 1.2 / Math.min(farnsWpm, wpm); // text speed
return {
dit: unit,
dah: unit * 3,
intra: unit,
letter: gapUnit * 3,
word: gapUnit * 7,
freq: parseInt(freqSlider.value, 10),
};









Prosign parser — SOS the correct way



A prosign is a Morse pattern that doesn't spal signal. SOS is the most famous. On the air

the proper SOS is one nine-symbol shape (`.. between the S, O, and S. Most Morsetranslators send SOS as three separate letters with 3-unit gaps in between, which is technically not a distress signal at all.



Fixed it with angle-bracket syntax. Type <S , , , ` and each

renders as one run-together shape:




CODE
function encode(input) {
return input.toUpperCase().split(' ').map((word) => {
const m = word.match(/^<([A-Z]+)>$/);
if (m && PROSIGNS[m[1]]) return PROSIGNS
return word.split('').map((ch) => TEXT_Tlean).join(' ');
}).filter(Boolean).join(' / ');
}






The decoder does the reverse — a token that matches a known prosign pattern with no internal spaces comes back as <XXX> in angle brackets, so a round-trip i






Puzzle share mode



Standard share links carry the plain text. Fine for showing a friend what a phrase looks like in Morse. Bad for setting a decoding challenge — the URL leaks the answer.



Puzzle share links carry only the Morse pattrce text:




CODE
learnmorsy.com/translator/?puzzle=1&m=....%20.%20.-..%20.-..%20---






The recipient's browser detects puzzle=1, -only main input, and shows a separate guess

field with Check and Reveal buttons. Anyone it.






Wrap up



Whole thing is under 500 lines of vanilla JS. No framework, no bundler, no backend. It runs offline once the page has loaded.



Try it: covers why PARIS is the reference word and how Farnsworth actually works.



There's a Koch-method Morse trainer app I'm shipping separately (iOS + Android + Apple Watch), but the translator is standalone and stays free. Feedback welcome, especially decoder edge cases I might have missed.

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
3 Quellen
GPT-6 Astra Release Today? OpenAI’s Next Major AI Model Is Almost Here
1 Quelle
Apple accuses OpenAI of destroying evidence as trade-secrets fight intensifies
1 Quelle
Major AI platforms go down in unprecedented simultaneous outage
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten I built a Morse code translator that renders WAV audio entirely in the browser

Thematisch verwandte Begriffe: built, Morse, code, translator · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...