Terence Eden’s Blog<p><strong>1KB JS Numbers Station</strong></p><p><a href="https://shkspr.mobi/blog/2025/07/1kb-js-numbers-station/" rel="nofollow noopener" translate="no" target="_blank"><span class="invisible">https://</span><span class="ellipsis">shkspr.mobi/blog/2025/07/1kb-j</span><span class="invisible">s-numbers-station/</span></a></p><p></p><p>Code Golf is the art/science of creating wonderful little demos in an artificially constrained environment. This year the <a href="https://js1024.fun/" rel="nofollow noopener" target="_blank">js1024 competition</a> was looking for entries with the theme of "Creepy".</p><p>I am not a serious bit-twiddler. I can't create JS shaders which produce intricate 3D worlds in a scrap of code. But I <em>can</em> use slightly obscure JavaScript APIs!</p><p>There's something deliciously creepy about <a href="https://priyom.org/number-stations" rel="nofollow noopener" target="_blank">Numbers Stations</a> - the weird radio frequencies which broadcast seemingly random numbers and words. Are they spies communicating? Commands for nuclear missiles? Long range radio propagation tests? Who knows!</p><p>So I decided to build one. <a href="https://js1024.fun/demos/2025/24/bar" rel="nofollow noopener" target="_blank">Play with the demo</a>.</p><p>Obviously, even the <a href="https://shkspr.mobi/blog/2020/09/a-floppy-disk-mp3-player-using-a-raspberry-pi/" rel="nofollow noopener" target="_blank">most extreme opus compression</a> can't fit much audio into 1KB. Luckily, JavaScript has you covered! Most modern browsers have a built-in Text-To-Speech (TTS) API.</p><p>Here's the most basic example:</p><pre><code>m = new SpeechSynthesisUtterance;m.text = "Hello";speechSynthesis.speak(m);</code></pre><p>Run that JS and your computer will speak to you!</p><p>In order to make it creepy, I played about with the rate (how fast or slow it speaks) and the pitch (how high or low).</p><pre><code>m.rate=Math.random();m.pitch=Math.random()*2;</code></pre><p>It worked disturbingly well! High pitched drawls, rumbling gabbling, the languid cadence of a chattering friend. All rather creepy.</p><p>But <em>what</em> could I make it say? Getting it to read out numbers is pretty easy - this will generate a random integer:</p><pre><code>s = Math.ceil( Math.random()*1000 );</code></pre><p>But a list of words would be tricky. There's not much space in 1,024 bytes for anything complex. The rules say I can't use any external resources; so are there any <em>internal</em> sources of words? Yes!</p><pre><code>Object.getOwnPropertyNames( globalThis );</code></pre><p>That gets all the properties of the global object which are available to the browser! Depending on your browser, that's over 1,000 words!</p><p>But there's a slight problem. Many of them are quite "computery" words like "ReferenceError", "URIError", "Float16Array". I wanted all the <em>single</em> words - that is, anything which only has one capital letter and that's at the start.</p><pre><code>const l = (n) => { return ((n.match(/[A-Z]/g) || []).length === 1 && (n.charAt(0).match(/[A-Z]/g) || []).length === 1);};// Get a random result from the filters = Object.getOwnPropertyNames( globalThis ).filter( l ).sort( ()=>.5-Math.random() )[0]</code></pre><p>Rather pleasingly, that brings back creepy words like "Event", "Atomics", and "Geolocation".</p><p>Of course, Numbers Stations don't just broadcast in English. The TTS system can vocalise in multiple languages.</p><pre><code>// Set the language to Russianm.lang = "ru-RU";</code></pre><p>OK, but where do we get all those language strings from? Again, they're built in and can be retrieved randomly.</p><pre><code>var e = window.speechSynthesis.getVoices();m.lang = e[ (Math.random()*e.length) |0 ]</code></pre><p>If you pass the TTS the number 555 and ask it to speak German, it will read out <i>fünfhundertfünfundfünfzig</i>.</p><p>And, if you tell the TTS to speak an English word like "Worker" in a foreign language, it will pronounce it with an accent.</p><p>Randomly altering the pitch, speed, and voice to read out numbers and dissociated words produces, I think, a rather creepy effect.</p><p>If you want to test it out, you can press this button. I find that it works best in browsers with a good TTS engine - let me know how it sounds on your machine.</p><p>🅝🅤🅜🅑🅔🅡🅢 🅢🅣🅐🅣🅘🅞🅝</p><p>With the remaining few bytes at my disposal, I produced a quick-and-dirty random pattern using Unicode drawing blocks. It isn't very sophisticated, but it does have a little random animation to it.</p><p>You can <a href="https://js1024.fun/demos/2025" rel="nofollow noopener" target="_blank">play with all the js1024 entries</a> - I would be delighted if you voted <a href="https://js1024.fun/demos/2025/24/bar" rel="nofollow noopener" target="_blank">for mine</a>.</p><p></p><p><a rel="nofollow noopener" class="hashtag u-tag u-category" href="https://shkspr.mobi/blog/tag/code/" target="_blank">#code</a> <a rel="nofollow noopener" class="hashtag u-tag u-category" href="https://shkspr.mobi/blog/tag/html/" target="_blank">#HTML</a> <a rel="nofollow noopener" class="hashtag u-tag u-category" href="https://shkspr.mobi/blog/tag/javascript/" target="_blank">#javascript</a> <a rel="nofollow noopener" class="hashtag u-tag u-category" href="https://shkspr.mobi/blog/tag/tts/" target="_blank">#tts</a></p>