Wie digitale Rauschgeneratoren funktionieren

Das Fundament: Pseudozufallszahlenerzeugung

Bei meiner Arbeit am Aufbau der Rausch-Engine von WhiteNoise.top habe ich Hunderte von Stunden damit verbracht, die Pipeline zu optimieren, die mathematische Zufälligkeit in überzeugendes Audio verwandelt. Jeder digitale Rauschgenerator beginnt mit der gleichen grundlegenden Komponente: einem Pseudozufallszahlengenerator, kurz PRNG. Ein PRNG ist ein Algorithmus, der eine deterministische Zahlenfolge erzeugt, die gemäß statistischen Tests zufällig erscheint. Echte Zufälligkeit aus Hardware-Entropiequellen ist zu langsam und unberechenbar für Echtzeit-Audio, daher bilden PRNGs die praktische Grundlage für jede digitale Rauscherzeugung.

Der einfachste für Audioarbeit geeignete PRNG ist der lineare Kongruenzgenerator (LCG), der jeden Wert als lineare Funktion des vorherigen Werts berechnet, modulo einer großen Konstante. Obwohl schnell, haben LCGs bekannte Schwächen: Sie zeigen Korrelationen zwischen aufeinanderfolgenden Abtastwerten, die hörbare Artefakte in Rauschsignalen erzeugen können. In meinen frühen Prototypen verwendete ich einen einfachen LCG und konnte beim Hören über hochwertige Kopfhörer schwache periodische Muster in der Ausgabe wahrnehmen. Diese Muster erschienen als schmale Spektralspitzen in der FFT-Analyse und bestätigten, dass die statistischen Schwächen des PRNG in den Audiobereich durchsickerten.

Für produktionsreifes Rauschen wechselte ich zum xorshift128+-Algorithmus, dem PRNG, der intern von den meisten JavaScript-Engines für Math.random() verwendet wird. Er hat eine Periode von 2 hoch 128 minus 1, hervorragende statistische Eigenschaften und vernachlässigbare Rechenkosten. Wenn ich die TestU01-Batterie von Zufallstests auf seine Ausgabe anwende, besteht er alle SmallCrush- und Crush-Suiten. Das Ergebnis ist ein Rauschsignal ohne hörbare Artefakte, mit einem flachen Spektrum, das über den gesamten hörbaren Bereich auf 0,3 dB genau verifiziert ist.

Von Zufallszahlen zu Audio-Abtastwerten

Ein PRNG erzeugt Zahlen, aber ein Audiosystem benötigt Wellenform-Abtastwerte bei bestimmten Amplituden und Abtastraten. Der Umwandlungsprozess umfasst Skalierung, Verteilungsformung und Pufferverwaltung. In meiner Implementierung gibt der PRNG vorzeichenlose 32-Bit-Ganzzahlen aus, die ich dann auf Gleitkommawerte im Bereich von minus eins bis plus eins normalisiere. Dies ist der Standard-Amplitudenbereich für digitales Audio in der Web Audio API und den meisten anderen Audio-Frameworks.

Die Verteilung der Zufallswerte beeinflusst den Charakter des Rauschens. Eine Gleichverteilung, bei der alle Werte im Bereich gleich wahrscheinlich sind, erzeugt Rauschen mit einer etwas anderen Amplitudenverteilung als die Gauß-Verteilung, die thermisches Rauschen in analogen Schaltungen charakterisiert. In der Praxis ist der Unterschied subtil: Gleichverteiltes weißes Rauschen hat einen Crest-Faktor von etwa 4,8 dB, während Gauß-verteiltes weißes Rauschen einen theoretisch unbegrenzten Crest-Faktor hat, obwohl er in der Praxis für typische Pufferlängen bei etwa 12 dB liegt. Für die meisten Anwendungen ist die Gleichverteilung völlig ausreichend und rechnerisch einfacher.

Wenn ich Gauß-verteiltes Rauschen für Anwendungen benötige, die es erfordern, verwende ich die Box-Muller-Transformation, die Paare gleichverteilter Zufallszahlen in Paare Gauß-verteilter Werte umwandelt. Der Rechenaufwand ist moderat – er verdoppelt die Kosten pro Abtastwert etwa –, aber das Ergebnis ist ein Rauschsignal, das die Amplitudenstatistik analoger Rauschquellen besser abbildet. In Hörtests ist der Unterschied zwischen gleichverteiltem und Gauß-verteiltem weißem Rauschen nahezu unhörbar, aber die Gauß-Variante schneidet in bestimmten Signalverarbeitungsanwendungen besser ab, bei denen die Amplitudenstatistik eine Rolle spielt.

Spektrale Formung: Aus Weiß werden Farben

Weißes Rauschen ist das Rohmaterial, aus dem alle anderen Rauschfarben erzeugt werden. Die Transformation erfolgt durch digitale Filterung – die Anwendung einer frequenzabhängigen Verstärkungskurve auf das Spektrum des weißen Rauschens. In meiner Rausch-Engine implementiere ich die spektrale Formung sowohl mit IIR- (Infinite Impulse Response) als auch mit FIR-Filtern (Finite Impulse Response), die jeweils unterschiedliche Vorteile bieten.

Für rosa Rauschen (minus drei Dezibel pro Oktave Abfall) verwende ich den Voss-McCartney-Algorithmus als Hauptmethode. Dieser Algorithmus unterhält mehrere unabhängige Zufallszahlengeneratoren, die mit unterschiedlichen Raten aktualisiert werden: einer aktualisiert bei jedem Abtastwert, einer bei jedem zweiten, einer bei jedem vierten und so weiter. Die Ausgaben werden summiert, um ein Signal zu erzeugen, dessen Spektrum den idealen Abfall des rosa Rauschens annähert. In meiner Implementierung verwende ich 16 Oktavschichten, was eine genaue spektrale Formung von unter 1 Hz bis über 20 kHz ermöglicht. Die Abweichung von der idealen Steigung beträgt weniger als 0,5 dB über den gesamten hörbaren Bereich.

Für braunes Rauschen (minus sechs Dezibel pro Oktave Abfall) verwende ich eine einfache Integration: Jeder Ausgabe-Abtastwert ist die Summe des vorherigen Ausgabewerts und eines neuen weißen Rausch-Abtastwerts, skaliert mit einem kleinen Koeffizienten. Mathematisch ist dies ein IIR-Tiefpassfilter erster Ordnung mit einem Pol, der sehr nahe bei eins auf dem Einheitskreis liegt. Die Herausforderung bei diesem Ansatz ist die Gleichspannungsdrift: Die laufende Summe kann im Laufe der Zeit weit von null abweichen und schließlich die Übersteuerungsschwelle überschreiten. Ich löse dies, indem ich einen sehr sanften Hochpassfilter erster Ordnung bei 5 Hz hinzufüge, der die Drift begrenzt, ohne das Spektrum über 20 Hz hörbar zu beeinflussen.

Für benutzerdefinierte Spektralformen, die von fortgeschrittenen Nutzern gewünscht werden, verwende ich einen parametrischen Equalizer aus kaskadierten Biquad-Filtersektionen zweiter Ordnung. Jede Sektion implementiert einen Standard-Filtertyp (Peak, Low Shelf, High Shelf oder Notch) mit vom Nutzer einstellbarer Frequenz, Verstärkung und Bandbreite. Durch die Verkettung von vier bis sechs Sektionen kann ich praktisch jede glatte Spektralform annähern, die ein Nutzer wünschen könnte – von sanften Neigungen bis hin zu komplexen Mehrband-Konturen.

Echtzeit-Erzeugung mit der Web Audio API

Die Web Audio API, die in allen modernen Browsern verfügbar ist, bietet die Infrastruktur für die Erzeugung und Wiedergabe von Rauschen in Echtzeit ohne serverseitige Verarbeitung. In meiner Implementierung bei WhiteNoise.top verwende ich drei Hauptkomponenten der Web Audio API: den AudioContext, den ScriptProcessorNode (oder seinen modernen Nachfolger, den AudioWorkletNode) und den BiquadFilterNode.

Der AudioWorkletNode ist der Ort, an dem die eigentliche Erzeugung stattfindet. Ich registriere einen benutzerdefinierten AudioWorkletProcessor, der in einem separaten Thread vom Haupt-Browser-Thread läuft und so sicherstellt, dass UI-Interaktionen keine Audio-Störungen verursachen. Die process()-Methode des Prozessors wird wiederholt mit einem Ausgabepuffer aufgerufen, typischerweise 128 Abtastwerte pro Aufruf bei 44,1 kHz. Innerhalb dieser Methode erzeuge ich weiße Rausch-Abtastwerte mit dem PRNG, wende eventuelle spektrale Formung an und schreibe die Ergebnisse in den Ausgabepuffer. Die gesamte Pipeline läuft auf moderner Hardware in etwa 0,01 Millisekunden pro Puffer – weit innerhalb der etwa drei Millisekunden langen Frist für störungsfreie Wiedergabe.

Die Pufferverwaltung ist entscheidend, um hörbare Artefakte zu vermeiden. Wenn der Prozessor zu lange braucht, um einen Puffer zu füllen, kommt es zu einem Audio-Output-Unterfluss, der ein Klicken oder Knacken erzeugt. In meinen Stresstests belaste ich das System, indem ich dem Haupt-Thread Rechenlast hinzufüge (wie umfangreiche DOM-Manipulation oder großes JSON-Parsing) und überprüfe, dass der Audio-Worklet-Thread weiterhin rechtzeitig Puffer liefert. Die Thread-Isolierung, die die AudioWorklet-API bietet, ist essenziell für diese Robustheit; der ältere ScriptProcessorNode lief im Haupt-Thread und war anfällig für Störungen während intensiver JavaScript-Ausführung.

Ich nutze auch den eingebauten BiquadFilterNode der Web Audio API für die spektrale Formung, wenn der gewünschte Filter ein Standardtyp ist. Diese Knoten sind in optimiertem nativem Code implementiert, was sie deutlich schneller macht als äquivalente JavaScript-Implementierungen. Für die Erzeugung von rosa Rauschen in einfacheren Konfigurationen kaskadiere ich mehrere BiquadFilterNodes, die als Tiefpassfilter mit sorgfältig gewählten Frequenzen und Q-Faktoren konfiguriert sind, um den idealen Abfall von minus drei Dezibel pro Oktave anzunähern.

Optimierungen und praktische Überlegungen

Leistungsoptimierung ist ein fortwährendes Anliegen bei der Echtzeit-Audioerzeugung. In meinem Entwicklungsprozess habe ich mehrere Techniken implementiert, um die Effizienz zu maximieren, ohne die Qualität zu beeinträchtigen. Die erste ist Vorberechnung: Für Rauschfarben, die sich nicht dynamisch ändern, erzeuge ich während der Initialisierung einen großen Puffer (typischerweise 10 Sekunden bei 44,1 kHz, also 441.000 Abtastwerte) und spiele ihn in einer Schleife ab. Damit die Schleife nicht hörbar ist, verwende ich am Schleifenübergang eine Überblendung, bei der die letzten 4.096 Abtastwerte des Puffers mit den ersten 4.096 Abtastwerten mithilfe eines Raised-Cosine-Fensters überblendet werden. Die resultierende Schleife ist wahrnehmungsmäßig nahtlos.

Die zweite Optimierung ist SIMD-artige Verarbeitung innerhalb von JavaScript. Obwohl JavaScript im AudioWorklet-Kontext keine expliziten SIMD-Befehle bereitstellt, strukturiere ich meine inneren Schleifen so, dass Abtastwerte in Vierergruppen verarbeitet werden, was dem JIT-Compiler der JavaScript-Engine eine automatische Vektorisierung ermöglicht. In meinen Benchmarks bringt dieser Ansatz eine Beschleunigung von 15 bis 25 Prozent im Vergleich zur Einzelverarbeitung, abhängig von der Browser-Engine.

Eine dritte Überlegung ist die Speicherverwaltung. Das Allokieren und Freigeben von Speicher während der Audioverarbeitung kann Garbage-Collection-Pausen auslösen, die hörbare Störungen verursachen. Ich allokiere alle Puffer während der Initialisierung vor und verwende sie während der gesamten Sitzung wieder. Innerhalb der process()-Methode werden keine Objekte erzeugt, und alle Zwischenwerte werden in vorab allokierten Typed Arrays gespeichert. Diese Disziplin eliminiert GC-bedingte Audio-Artefakte vollständig.

Der Stromverbrauch ist ein weiteres praktisches Anliegen, insbesondere für mobile Geräte. Bei meinen Tests auf Smartphones habe ich festgestellt, dass die CPU-Last eines einfachen Rauschgenerators vernachlässigbar ist – typischerweise weniger als ein Prozent. Allerdings verhindert ein aktiver Audioausgang, dass das Gerät in tiefe Schlafzustände übergeht, was den Akku bei längeren Sitzungen entladen kann. Ich mildere dies, indem ich eine Timer-Funktion anbiete, die den Generator nach einer vom Nutzer festgelegten Dauer stoppt, und indem ich die Page Visibility API nutze, um die Erzeugung zu pausieren, wenn der Browser-Tab nicht im Vordergrund ist.

Validierung der Ausgabequalität des Generators

Ein Rauschgenerator ist nur so gut wie seine Ausgabequalität, und Qualität muss durch objektive Messungen verifiziert werden. In meinem Qualitätssicherungsprozess lasse ich jede Generatorkonfiguration durch eine Suite automatisierter Tests laufen, bevor ich sie für Nutzer freigebe. Der erste Test ist die spektrale Flachheit: Ich erfasse eine 60-Sekunden-Probe weißen Rauschens, berechne die gemittelte FFT-Amplitude und überprüfe, dass kein Frequenz-Bin um mehr als 1 dB vom Mittelwert abweicht. Bei geformtem Rauschen vergleiche ich das gemessene Spektrum mit der Zielkurve und überprüfe, ob die Abweichung weniger als 0,5 dB beträgt.

Der zweite Test ist die Amplitudenverteilung. Ich berechne ein Histogramm der Abtastwerte und vergleiche es mit der erwarteten Verteilung – ob gleichverteilt oder gaußverteilt – mithilfe des Kolmogorow-Smirnow-Tests. Ein p-Wert über 0,05 zeigt an, dass die Verteilung die erwartete Form auf dem 95-Prozent-Konfidenzniveau abbildet.

Der dritte Test ist die Periodizitätserkennung. Ich berechne die Autokorrelationsfunktion einer 10-Sekunden-Probe und überprüfe, dass keine Verzögerung ungleich null einen Korrelationskoeffizienten aufweist, der das theoretische Maximum für einen Zufallsprozess dieser Länge überschreitet. Periodische Muster im PRNG würden als Spitzen in der Autokorrelationsfunktion erscheinen, selbst wenn sie nicht hörbar sind, und auf einen Fehler im Generator hindeuten, der in Signalverarbeitungsanwendungen Probleme verursachen könnte.

Schließlich führe ich subjektive Hörtests mit Kopfhörern durch und prüfe auf Klicks, Knackser, tonale Artefakte und Schwankungen in Pegel oder Klangfarbe über längere Wiedergabezeiträume. Automatisierte Tests erkennen die meisten Probleme, aber das menschliche Ohr bleibt der ultimative Richter der Audioqualität, und ich mache es mir zur Gewohnheit, jede Generatorvariante persönlich anzuhören, bevor sie auf der Plattform live geht.

Quellenangaben

Haeufig gestellte Fragen

Kann ein digitaler Rauschgenerator wirklich zufällige Ausgaben erzeugen?

Nein. Digitale Rauschgeneratoren verwenden Pseudozufallszahlengeneratoren (PRNGs), die deterministische Sequenzen erzeugen. Ein gut konzipierter PRNG erzeugt jedoch Ausgaben, die für alle praktischen Audioanwendungen statistisch nicht von echter Zufälligkeit zu unterscheiden sind.

Warum verwendet die Web Audio API AudioWorklet statt ScriptProcessorNode?

AudioWorklet läuft in einem separaten Thread vom Haupt-Browser-Thread und verhindert so, dass UI-Operationen Audio-Störungen verursachen. ScriptProcessorNode lief im Haupt-Thread und war anfällig für Aussetzer bei intensiver JavaScript-Ausführung. ScriptProcessorNode ist mittlerweile veraltet.

Was verursacht Klicks oder Knackser in einem Rauschgenerator?

Klicks und Knackser werden typischerweise durch Puffer-Unterläufe verursacht, bei denen der Generator den Ausgabepuffer nicht rechtzeitig füllen kann, oder durch Garbage-Collection-Pausen in JavaScript. Ordnungsgemäße Pufferverwaltung und Vorab-Allokierung von Speicher beseitigen diese Artefakte.

Wie viel CPU verbraucht ein Rauschgenerator?

Ein einfacher Rauschgenerator verbraucht auf moderner Hardware typischerweise weniger als ein Prozent CPU. Das Hauptanliegen bei der Leistung ist die Aufrechterhaltung eines konsistenten Timings, um Audio-Störungen zu vermeiden, nicht die Gesamt-CPU-Last.

Kann ich eine Rauschprobe in einer Schleife abspielen, anstatt sie in Echtzeit zu erzeugen?

Ja, aber Sie müssen am Schleifenübergang eine Überblendung anwenden, um ein hörbares Klicken zu vermeiden. Eine Raised-Cosine-Überblendung von etwa 4.096 Abtastwerten bei 44,1 kHz erzeugt eine wahrnehmungsmäßig nahtlose Schleife.

Leo Chen

Leo Chen ist ein Werkzeug-Entwickler und Audio-Enthusiast, der sich auf die Erstellung praktischer Online-Tools fuer Klang und Produktivitaet spezialisiert hat.