Het simuleren van Airband AM-radio's

De afgelopen jaren heb ik bijna elke zaterdag doorgebracht met het spelen van (en af en toe werken aan) BMS, een moderne¹ combat flight sim waarin jij en je vrienden in virtuele F-16's dingen opblazen. Elke co-op game met meer dan 30 personen is fantastisch, maar luchtgevechten zijn extra leuk omdat het zo'n teamsport is. Vliegtuigen draaien in hevige dogfights en spelen dodelijke spelletjes 'whack-a-mole' met vijandelijke luchtverdediging, allemaal om een paar jets een paar seconden boven het doelwit te geven om hun bommen te droppen. Niets hiervan is gescript en iedereen moet samenwerken om levend terug te keren.

Je zou denken dat dit gepaard gaat met veel communicatie, en daarom wordt BMS geleverd met een voice-chat app genaamd IVC. Om de immersie te vergroten, simuleert deze de radio's in je virtuele cockpit. Je meldt je niet aan bij een chatroom, maar stemt af op een radiofrequentie. Je signaal zwakt af naarmate je jet verder weg vliegt van degene met wie je praat, of als jullie beiden laag vliegen, kan het signaal volledig geblokkeerd worden door het terrein.

Verrassend genoeg zijn vliegtuigradio's — zelfs veel militaire exemplaren — nog steeds eenvoudige AM-sets die werken in de VHF- en UHF-banden. Een van de redenen waarom dit na decennia van technologische vooruitgang is blijven bestaan, is dat AM-radio geen "capture effect" heeft. Wanneer twee mensen op dezelfde frequentie uitzenden, kun je beide partijen nog (soort van) horen, in tegenstelling tot FM waarbij het luidere signaal het stillere signaal dempt of "vangt" (captures).

Wanneer gevechtspiloten over elkaar heen praten, klinkt dat specifiek. Echter, wanneer mensen in IVC elkaar onderbreken, maakt de software een geluid dat mij meer irriteert dan zou moeten. Toen een vriend een vervanger voor IVC begon te bouwen met een betere UX en moderne audiocodecs, wilde ik graag bijdragen door realistische AM-radio-dynamiek toe te voegen.

Hoe we dat aanpakken, leggen we nu uit.

Radio 101: padverlies, decibels en SNR

Laten we de "zwarte magie" van antenne-ontwerp buiten beschouwing laten en uitgaan van het feit dat als je een draad van de juiste lengte knipt en de elektronen daarin laat trillen, sommige van hen als elektromagnetische golven de ruimte in schieten.

Zelfs als die golven niets raken,² worden ze zwakker volgens het kwadraat van de straal $r$ vanaf de zendende antenne, simpelweg omdat ze zich verspreiden tijdens hun reis. Dit geldt voor alle golven: geluid, radio en licht.³

Omdat verschillende afstanden tot de bron zulke extreem verschillende vermogensniveaus produceren, moeten onze zintuigen werken op logaritmische schalen. Het is verbazingwekkend: het gebrul van een straalmotor is een miljoen keer luider dan de zachtste fluistering, en je kunt beide horen. Een kamer kan een miljoen keer donkerder zijn dan een zonnige dag, en toch kun je in beide situaties zien.

De wereld van radiofrequenties (RF) is niet anders. Omdat het onhandig zou zijn om met zo'n breed scala aan getallen te werken, beschrijven we signaalsterkte vaak op een logaritmische schaal die decibels wordt genoemd, afgekort als dB.

Een van de eerste zaken die we in decibels willen beschrijven is de signaal-ruisverhouding, of SNR (Signal-to-Noise Ratio). Decibels zijn altijd een dimensieloze ratio tussen twee waarden, waarbij 0 dB "gelijk" betekent, en elke $\pm 3$ dB het vermogen ongeveer verdubbelt of halveert. Bij SNR betekent 0 dB dus dat het signaal evenveel vermogen heeft als de ruis.

Ruis kan door mensen worden veroorzaakt, kan voortkomen uit atmosferische gebeurtenissen zoals onweersbuien, of kan uit de ruimte komen. Daarnaast is er ruis door imperfecties in de elektrische componenten van je radio. Zelfs als je al die ruis zou kunnen verwijderen, zou je nog steeds de thermische energie horen die de elektronen in je ontvanger laat vibreren (dit fenomeen noemen we thermische ruis en het is ons theoretische minimum).

Ruis is dus altijd aanwezig. We kunnen het nooit volledig verwijderen; we hopen alleen dat het ontvangen signaal luider is dan de ruis op het moment dat het ons bereikt.

Amplitudemodulatie

Welke golven moet je uitzenden? De frequenties die jouw stem (en alles wat je hoort) vormen, liggen tussen de 20 en 20.000 cycli per seconde, of Hertz. Maar hoe lager de frequentie, hoe langer de golflengte, en goede antennes zijn ten minste een kwart van de golflengte die ze ontvangen. Om een signaal van 10 kHz op te vangen, zouden we meer dan 7 kilometer draad nodig hebben.⁴

In plaats daarvan verschuiven we onze stem naar een hogere draaggolf-frequentie die we wel kunnen verzenden. Een eenvoudige aanpak is om de amplitude van de draaggolf te moduleren met die van onze stem. Dit noemen we amplitudemodulatie, of kortweg AM.

Onze stem wordt op een hogere draaggolf geplaatst door deze te vermenigvuldigen met een modulatie-index $k$. De frequentie van de draaggolf blijft volledig ongewijzigd. De resulterende vorm van het AM-signaal — de envelop — is een gespiegelde kopie van onze stem.

Wat zit er in een radio?

Als we voorbijgaan aan hoe je een radio afstemt op verschillende frequenties, blijven er nog een paar problemen over om op te lossen als we een AM-signaal willen horen:

  1. We moeten alle frequenties wegfilteren waar we niet om geven en alleen de band van frequenties doorlaten die we daadwerkelijk willen (de passband).
  2. Het signaal is waarschijnlijk erg zwak tegen de tijd dat we het ontvangen, dus we moeten het versterken.
  3. Tot slot gebruiken we een envelopdetector om onze stem weer uit het AM-signaal te extraheren, oftewel te demoduleren.

Filtering

Hoe laten we sommige frequenties door en blokkeren we andere? In de analoge wereld hebben we te maken met:

  • Stroom (I): elektronen die door ons circuit stromen.
  • Spanning (V): de elektrische potentiële energie tussen twee delen van een circuit.
  • Weerstand (R): de mate waarin een onderdeel van een circuit de stroomstroom tegenhoudt.

Deze zijn altijd aan elkaar gerelateerd volgens de wet van Ohm: $V = IR$

Met deze kennis kunnen we een van de eenvoudigste analoge circuits maken: een spanningsdeler. Omdat weerstanden de stroomstroom tegenwerken, zal onze uitgangsspanning een fractie zijn van de ingangsspanning, gebaseerd op de ratio van de twee weerstanden: $V{out} = V{in} \cdot \frac{R2}{R1 + R_2}$

Wat gebeurt er als we een van de weerstanden vervangen door een condensator (een onderdeel dat elektrische lading opslaat tussen twee platen en deze later kan ontladen)? Dan krijgen we het volgende gedrag: $V{out}(t) = V{in} \cdot (1 - e^{-t/RC}) + V_0 \cdot e^{-t/RC}$

Naarmate de tijd $t$ verstrijkt, nadert $V{out}$ asymptotisch $V{in}$ met een snelheid die wordt bepaald door de weerstand $R$ vermenigvuldigd met de capaciteit $C$. Daarom noemen we $RC$ de tijdconstante, of $\tau$.

Wanneer een condensator een wisselende input krijgt (zoals een golf van een antenne) in plaats van een constante, gebeurt er iets interessants: omdat de condensator constant oplaadt en ontlaadt, neemt zijn weerstand⁵ af naarmate de frequentie toeneemt. Dit maakt ons RC-circuit een laagdoorlaatfilter (low-pass filter) dat lage frequenties doorlaat en hoge frequenties dempt (attenueert). Als we de weerstand en condensator omwisselen, hebben we een hoogdoorlaatfilter (high-pass filter), waarbij lage frequenties worden gedempt.

Automatische versterkingsregeling (AGC)

We moeten ons signaal ook versterken. Maar hoeveel? Omdat we signalen met zeer verschillende sterktes ontvangen, is het wenselijk dat onze radio een consistent volumeniveau heeft wanneer iemand praat. We willen de versterking, of gain, automatisch regelen.

Dit doen we opnieuw met filters. Als we de amplitude van ons signaal nemen en deze door een laagdoorlaatfilter halen, krijgen we een curve die een ruwe maat is van het volume.

We hebben echter een klein probleem: we willen dat het filter snel reageert wanneer iemand begint te praten, maar langzaam afneemt, zodat het gemeten volume niet wegvalt wanneer iemand een adempauze neemt. Hiervoor bouwen we een filter dat anders reageert wanneer het signaal stijgt (attack) dan wanneer het signaal daalt (decay).

Als we de binnenkomende audio delen door deze berekende waarde, zou de gebruiker altijd een vergelijkbaar volume moeten horen.

AM-demodulatie

Een filter dat de omtrek van een signaal volgt, wordt soms een "envelopdetector" genoemd. Om ons AM-signaal terug te demoduleren naar de verzonden stem, hoeven we het signaal simpelweg door een dergelijk laagdoorlaatfilter te halen.

Squelch

Niemand vindt het prettig om lange tijd naar statische ruis te luisteren. Daarom kregen radio's een functie genaamd squelch, die de luidsprekers dempt zodra het signaal onder een bepaald volumeniveau zakt.

Wanneer je naar airband-radio's luistert, ben je waarschijnlijk bekend met een "klik" wanneer iemand begint te praten en een "kssh" wanneer ze stoppen. Dit is geen kunstmatig geluidseffect, maar een natuurlijk product van de interactie tussen AGC en squelch.

Wanneer een transmissie begint en het gemeten volume boven de ruisvloer schiet, springt de squelch-poort open terwijl de AGC snel probeert het signaal te dempen. De resulterende 'pop', beperkt door onze bandbreedte, verzacht tot een klikkend geluid. Wanneer de transmissie stopt, draait de AGC het volume snel weer omhoog, waardoor we de ruis horen instromen voordat de squelch-poort weer dichtklapt.

Interferentie

Waar komen die vreemde geluiden vandaan wanneer meerdere mensen tegelijk praten?

Elektronische oscillatoren driften een beetje, vooral door temperatuurverschillen. Daarnaast verschuift het Doppler-effect de frequentie van alles wat wordt uitgezonden wanneer iemand beweegt. In een gevechtsvliegtuig dat honderden knopen vliegt, kan deze verschuiving aanzienlijk zijn.

Een AM-ontvanger merkt hier meestal niets van. Als je denkt dat je op 121.5 MHz bent afgestemd, maar je zit eigenlijk op 121.4999 MHz, demoduleert de envelopdetector nog steeds exact dezelfde envelop.

Dat verandert echter zodra meerdere mensen tegelijk praten. Wanneer frequentie $A$ tegelijk met frequentie $B$ wordt afgespeeld, ontstaat er een zwevingsfrequentie (beat frequency) op $|B - A|$. Terwijl de draaggolven zelf honderden keren hoger zijn dan de bandbreedte van de radio en het menselijk oor, zijn de zwevingen dat niet. Een zender op 121.499 MHz en een andere op 121.501 MHz geven ons een zeer hoorbare en irritante piep van 2 kHz.

Deze zwevingen veroorzaken ook vreemde effecten in de envelop:

  • Stemmen worden ring-gemoduleerd door de zwevingsfrequenties (denk aan Daleks).
  • Luidere stemmen moduleren de amplitude van zwakkere stemmen.
  • In extreme gevallen stijgt en daalt de envelop zo snel dat de AGC het volume razendsnel laat "pompen".

Nu met de computer!

Computers werken niet met continue analoge waarden. In plaats daarvan samplet een analoog-naar-digitaal omzetter (ADC) de spanning van een microfoon duizenden keren per seconde naar getallen.

Voor digitale filtering lijkt de formule in de digitale wereld sterk op de analoge versie. Voor een lijst met samples $x[n]$ wordt elke output $y[n]$ berekend uit de huidige sample en de vorige output: $y[n] = \alpha \cdot x[n] + (1 - \alpha) \cdot y[n - 1]$

waarbij voor een sampleperiode $T$ of samplefrequentie $Fs$: $\alpha = 1 - e^{-1/(Fs \cdot \tau)}$

Voor onze AGC gebruiken we verschillende $\tau$-waarden, afhankelijk van of $x[n] \geq y[n-1]$.

IQ-sampling

Om de interferentie van meerdere zenders te simuleren, moeten we kijken naar hoe we frequenties representeren. Een enkele sinus is ambigu; op de meeste momenten kun je de fase van het signaal niet bepalen.

Als we een frequentie representeren met twee sinusgolven — zowel een cosinus als een sinus — die 90 graden uit fase zijn, is de fase nooit ambigu. Deze representatie noemen we "in-phase and quadrature encoding", of kortweg IQ.

In de wereld van RF-engineers worden deze fasoren vaak uitgedrukt als complexe getallen met behulp van de formule van Euler: $e^{j\theta} = \cos(\theta) + j \cdot \sin(\theta)$ (In de elektrotechniek gebruiken we $j$ in plaats van $i$ voor de imaginaire eenheid, omdat $i$ staat voor stroom).

Een basisband AM-simulatie

We simuleren de radio's in basisband — dat wil zeggen, alleen de audiofrequenties die gedemoduleerd zouden worden door de envelopdetector. Een volledige simulatie van draaggolven boven de 100 MHz zou in real-time te zwaar zijn voor een CPU.

Voor $m$ radio's die tegelijk uitzenden op draaggolven $C1, C2, \dots, Cm$, maken we een lijst van relatieve frequenties $Fm = Cm - C1$. De eerste frequentie $C_1$ wordt onze "nul"-frequentie.

Bij een samplefrequentie $Fs$ is de fasehoek voor elk signaal: $\thetam[n] = 2\pi \cdot Fm \cdot n / Fs$

We representeren elk signaal als een product van die fasor, de SNR$m$, en de samples $xm[n]$ vermenigvuldigd met de modulatie-index $k$: $Im[n] = \text{SNR}m \cdot (1 + xm[n] \cdot k) \cdot \cos(\thetam[n])$ $Qm[n] = \text{SNR}m \cdot (1 + xm[n] \cdot k) \cdot \sin(\thetam[n])$

Vervolgens tellen we alle IQ-vectoren op, inclusief wat willekeurige ruis ($RI[n], RQ[n]$): $I[n] = RI[n] + \sum{i = 1}^m \text{SNR}i \cdot (1 + xi[n] \cdot k) \cdot \cos(\thetai[n])$ $Q[n] = RQ[n] + \sum{i = 1}^m \text{SNR}i \cdot (1 + xi[n] \cdot k) \cdot \sin(\thetai[n])$

De hoorbare envelop is simpelweg de lengte van die IQ-vector: $E[n] = \sqrt{I[n]^2 + Q[n]^2}$

Dit resultaat sturen we door ons AGC-filter, passen we squelch toe wanneer het volume onder de drempelwaarde zakt, en gebruiken we een banddoorlaatfilter om het te beperken tot de AM-bandbreedte (ongeveer 300 Hz tot 3–5 kHz).

Het resultaat klinkt zeer realistisch. De enige inputs zijn de signalen en hun relatieve sterktes, willekeurige ruis, de attack/decay constanten voor de AGC en de grenzen van het banddoorlaatfilter.

De les hier is dat, hoewel een simulatie nooit exact als het echte leven zal zijn, je verrassend dichtbij kunt komen met relatief weinig code als je het probleem vanuit eerste principes benadert.

***

¹ In tegenstelling tot Tweede Wereldoorlog-sims zoals IL-2, betekent "modern" hier vooral "heeft jets en raketten", met een focus op de jaren '80–2000. ² OpenFreq voert ook line-of-sight controles uit en past wiskunde toe wanneer signalen onder een flauwe hoek langs het terrein scheren. ³ Zie video's over dit onderwerp voor meer verdieping. ⁴ Dit voorkomt niet dat supermachten antennes bouwen om met onderzeeërs onder water te communiceren via Extremely Low Frequency (ELF) comms. ⁵ Eigenlijk gaat het hier om impedantie, de term voor weerstand die kan veranderen over tijd of frequentie. ⁶ De extra 4.1 kHz werd eind jaren '70 gekozen voor CD-audio om filters extra ruimte te geven. ⁷ De term "imaginaire getallen" werd bedacht door Descartes als een klacht over hoe nutteloos hij ze vond. Euler bewees het tegendeel, maar we gebruiken de belediging van Descartes nog steeds.