ich habe mir einen Rauschgenerator gebaut mit einem AVR ATtiny26. Mega simples Design: PRNG erzeugt 8-Bit Wort, wirft es auf PORTA, R2R, Verstärker, Lautsprecher.
Es geht nicht um irgendwie physikalisch korrektes rosa/braunes Rauschen, sondern darum, dass das -- klingt blöd, weiß ich -- "sanft" klingt und eben in Software "abschwächbar" ist. Konkret verändere ich also die Verteilung Energie/Frequenz in Software.
Das ist unheimlich simpel: Ich habe einen 8-Bit Akkumulator, der jeweils auf PORTA ausgegeben wird. In jeder Iteration wird der durch
accu += (prng() / divisor)
Voller Code:
formatting link
Verändert. Je größer "divisor", desto "sanfter" das Rauschen. Prinzipiell funktioniert das auch prima, mit einer Einschränkung: In der Praxis erhalte ich mit größeren Divisor-Werten auch immer ein lästiges knacksen.
Da das immer an denselben Stellen auftritt in demselben Pattern (ist ja ein 100% deterministischer PRNG) nehme ich an, dass das an der Division liegt, die auf dem AVR in Software emuliert wird und daher nicht Laufzeitkonstant ist.
Jetzt habe ich überlegt, wie ich das besser machen kann. Klar, kann nur Zweierpotenzen als Teiler zulassen, aber dann ist der Unterschied zwischen zwei Levels recht stark. Fällt jemandem eine gute Idee ein, wie man das ohne Hardwaredivision, nur mit Integerarithmetik und in konstanter Laufzeit hinkriegt? Mir fehlt gerade eine gute Idee dafür.
Viele Grüße, Johannes
Didn't find your answer? Ask the community — no account required.
Du meinst, ein einfacher 7810 wäre überfordert? Ich hätte jetzt...
C
Christian Zietz
Johannes Bauer schrieb:
Hat der µC denn einen HW-Multiplizierer (8 x 8 = 16)? Dann könntest Du recht einfach berechnen: prng() * x / 256 ( = prng() / (256/x)) und hättest immerhin 255 Stufen zur Auswahl.
Grüße Christian
J
Johannes Bauer
Oh, die Idee ist gut! Im vorliegenden Fall geht das leider nicht, habe auch keinen HW-Multiplizierer, aber kommt definitiv in die Trickkiste.
Habe ein bisschen damit herumexperimentiert eine Bitmaske zu einem gegebenen Maximalwert vorauszuberechnen (das ist dann nur eine Subtraktion im Worst-case), aber irgnedwo ist da noch ein Wurm drin. Siehe
formatting link
Vielen Dank & viele Grüße, Johannes
R
Roland Krause
Am 06.10.19 um 09:43 schrieb Johannes Bauer:
Moin, mir ist nicht ganz klar, wie Dein Wert für "value" kleiner 0 werden soll. prng() liefert ja einen uint, also Werte von 0-255. Also Deine Zuweisungen value = 0 sollte den Knackser auslösen. value >
255 solltest Du nie erreichen.
Meiner Meinung nach müsste das so aussehen:
while (true) { uint8_t value = prng() / divisor; if (enabled) { PORTA = value; } else { PORTA = 0; } }
Gruß
C
Christian Zietz
Johannes Bauer schrieb:
Ist denn die (in SW durchgeführte) Division grundsätzlich zu langsam oder stört nur deren eingangswertabhängige Laufzeit? Falls letzteres, kannst Du ja die Worst-Case-Samplerate bestimmen, d.h. die erreichbare Samplerate bei den ungünstigsten Eingabewerten. Und dann diese Samplerate erzwingen, indem Du die Samples nicht gleich am Ende der Berechnung sondern z.B. timer-gesteuert ausgibst.
Grüße Christian
PS: Hier mangels HW-Multiplikator nicht hilfreich, aber dennoch viel zu wenig bekannt: Man kann auch die Division durch viele Ganzzahlen durch Multiplikation und Shifts hinbekommen. Code sagt mehr also Worte:
formatting link
. gcc vermeidet hier die (auch auf einem x86 teure) Division durch 3.
R
Roland Krause
Am 06.10.19 um 10:46 schrieb Roland Krause:
.. und prng() würde ich durch rand() ersetzen, so heißt die Funktion zumindest beim XC8 (PIC, Microchip). Dann sollte das klappen.
V
Volker Bartheld
Reicht Dir eine "logarithmische" Lautstärkeskala mit 8 Stufen? Dann könntest Du einfach nach rechts shiften statt zu teilen, hast dann aber...
Wenn Dein ATtiny noch ein bisserl PLatz im EEPROM hat, kannst Du dort auch einfach eine Rauschtabelle ablegen. die 128 Bytes reichen evtl. dafür. Teilen mußt Du dann aber natürlich immer noch.
Externe Beschaltung mit Rauschdiode am ADC scheidet kategorisch aus?
Ciao, Volker
M
Marcel Mueller
Am 06.10.19 um 09:43 schrieb Johannes Bauer:
Zufallsbits, die von prng kommen. Sehr deutlich wird das bei Zweierpotenzen. Diese entsprechen einem Shift-Operator, der einfach die unteren Bits entsorgt.
Divisor ja auch noch konstant ist.
Berechne doch mal die Folge auf dem PC vor und schau dir das Ergebnis mit Audacity an.
einfachsten Fall ist das ein Integrator (Addition), dann gibt es erst
bekommst, sonst ist das Spektrum komplett im Eimer.
Addition abziehen und somit eine Eskalation des Akkumulators
Das bringt mich zum zweiten Punkt: in jedem Fall braucht der Akkumulator mehr Bits (also faktisch 16), von denen nur die obersten an den ADC
obigem Muster kompensierten Akkumulatorwerte zwar ebenfalls tiefpassfiltern, aber es hat eben auch eine Resonanzfrequenz unterhalb
weg, die letztlich DAC-Headroom kosten, von denen der 8-Bitter ohnehin viel zu wenig hat.
Man braucht also am besten einen Bandpass mit einer sehr schlechten
Technisch ist ein IIR Filter ein bisschen +,-,*. Division braucht man
zu Samplingrate alle nahe bei ganzen Zahlen. Daher bietet es sich an,
Beispiel: b1 = -1,98; per Definition sind die oberen 8 Bit des
unteren 8 Bit die Nachkommastellen. b1 * y[n-1] = b1' * y[n-1] - (y[n-1] > 5) - (y[n-1] > S Man beachte die Shift-Richtung. Per Definition sind x[n] Vorkommastellen, also die oberen 8 Bit. Diese werden multipliziert mit
Multiplikationsergebnisses sind am Ende Vorkommastellen, die unteren Nachkomma, exakt passend zu dem y-Akkumulator. Allerdings wird man schnell feststellen, dass der y-Akkumulator auf
oberen 8 Bit des Multiplikationsergebnisses werden nur zu den Nachkommastellen des y-Akkumulators addiert. Damit muss man nur noch bei
den Frequenzgang. Am Ende muss man ausprobieren, wie weit hoch man sich traut. Es ist
gar keine Multiplikation mit a0. Damit bekommt man die weiter reduzierte Formel:
-20dB/Dekade sind analog als Filter billig zu haben, das ist ein 1pol Tiefpaß.
MfG JRD
M
Marte Schwarz
Hi Rafael,
Nicht wirklich, erst dann, wenn man ca 1/2 Dekade jenseits der Eckfrequenz des Filters ist. Über den gesamten Frequenzbereich sind wir beim Integrator erster Ordnung. Wenn man nun die Steilheit auf die Potenz 5/3 reduzieren wollte, könnte man auf die Idee kommen, dass man ein Mischer bräuchte, der dem -20 dB eben noch einmal das Orginalsignal zumischte, wäre da nicht der Phasengang des Integrators. Also müsste man mit einem Allpassfilter den Phasengang des ungefilterten Signals dem des Integrators anpassen, bevor man summiert... Könnte zielführend werden, wenn das mit den idealen Integratoren in der Praxis nicht regelmäßig an Offsets scheitern würde.
Marte
R
Rafael Deliano
Auch die -3dB Schaltungen funktionieren nur über begrenzten Frequenzbereich, typisch 2 Dekaden. Für die üblichen Anwendungen ist nicht mehr erforderlich.
MfG JRD
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required
Report Content
You are reporting this content to the moderators. They will look at it
ASAP.