Das Reverb (- oder Hall) ist ein Effekt, der die Schallreflektionen und dadurch die Umgebungscharakteristika abbildet. Es gibt grundsätzlich zwei Kategorien der Hall-Implementierungen.
- Faltungshall (engl. convolution reverb)
- Algorithmischer Hall (engl. algorithmic reverb)
Faltungshall
Die Theorie ist einfach: Hierbei wird die Impulsantwort eines realen Raums aufgenommen. Dann wurde diese Impulsantwort auf jeden(!) Sample angewendet. Wenn man bedenkt, dass so eine Impulsantwort für größere Räume mehrere Sekunden lang ist, bedeutet das, dass man für jeden Sample tausende von Folgesamples berechnen muss, speichern muss und diese dann irgendwie miteinander addieren muss. Wenn man es also ganz simpel auf der Zeitebene betreibt, ist es quasi eine Aufgabe der Unmöglichkeit. Selbst die schnellsten Desktop-Prozesoren kommen da an ihre Grenzen alleine für diese Aufgabe.
Das ganze man aber auf der Frequenzebene berechnen! Dieser Prozess der Impulsapplikation kann mit Hilfe der Faltungsoperation erledigt werden. Man faltet die Impulsantwort quasi auf die Samplereihe. Nichtsdestotrotz: Dafür muss das Signal auf die Frequenzebene (in halbwegs akzeptabler Qualität) transformiert werden, dort daraus der Hall berechnet und zurück auf die Zeitebene transformiert werden. Auch diese Operationen ist bei vielen DSPs nicht drin, (die üblicherweise auch Luft haben müssen, was anderes als Reverb zu berechnen).
Da früher die Rechenleistung der DSPs viel niedriger waren, sind algorithmische Reverbs entstanden.
Algorithmischer Hall
Algorithmische Halls sind Effekte, die einen imaginären Raumeffekt mit verschiedenen Algorithmen abbilden. Diese Algorithmen müssen -im Gegensatz zum Convolution reverb- keinen Bezug zur Realität haben. Sie sollen den Effekt eben nur nachmachen. Es gibt unzählige Algorithmen in der Reverbgeschichte von jedem Hersteller, die aber oft auf Grundelemente zurückgreifen. Diese sind:
Viele algorithmische Reverbs basieren auf empirische Ansätze anstatt analytische. D.h. oft sind die Parameter und Designs als ein Kompromiss zwischen Effektqualität und Recheneffizienz entstanden. Die Ermittlung der Parameter (und Designs) basieren auf Hörerlebnissen und Wahrnehmung des Halleffekts.
Denn der Halleffekt ist strenggenommen auch theoretisch nichts anderes als eine Summe der unendlichen Reflektionen – also Delays. Diese nehmen wir nur hierbei nicht einzeln wahr sondern eben als deren Gesamtheit – als Halleffekt.
Das heißt, es macht unserem Ohr keinen Unterschied, auf welche Mikrosekunde genau eine Reflektion ankommt. Vielmehr ist ein gesamtes Klangbild entscheidend. Deshalb erzielt man diese Reflektionen mit Hilfe der parallel geschaltete Kammfilter (Im Prinzip Delay lines) und reihengeschaltete Allpassfilter. Mit Hilfe dieser Filter werden Reflektionen in Schleife vermehrt und gedämpft. Das schwierigste dabei ist die Bestimmung der Parameter, sodass keine unerwünschte Effekte auftreten bzw. das Klangbild soweit wie möglich unseren Vorstellungen passt.
Parameter
Folgende Kontrollparameter sind für Halleffekte üblich:
Raumgröße
Einstellung der Raumgröße beeinflußt die Rückkopplung der Kamm- und Allpassfilter. Je größer die Rückkopplung, desto langsamer klingt eine Reflektion ab und das erweckt den Eindruck eines größeren Raums
Dry/Wet
Wieviel Effektanteil ins Ausgangssignal gemischt werden soll.
Dämpfung
Mit dem Dämpfungsparameter wird die Dämpfung der Kammfilter kontrolliert. Je größer die Dämpfung, desto steiler klingen die Reflektionen ab.
Frequenzfilter
Mit Frequenzfiltern , üblicherweise mit Hochpass und Tiefpass, wird die Klangcharakteristik des Halls beeinflusst.
Pre-Delay
Der Mensch kann die ersten Reflektionen eines Raums wahrnehmen, weil die noch sauber und einzeln hörbar sind. Deshalb kann man ein paar Delay-Linien mit kleineren Verzögerungen einbauen, um den Effekt realistischer zu machen.
Freeverb Reverb-Algorithmus
Soweit die Einführung zur Reverb-Algorithmik. Ein freier und beliebter Algorithmus ist der Freeverb-Algorithmus. Dieser basiert auf alter Schröder-Algorithmus. Dieser verwendet acht Kammfilter parallel und anschließend vier Allpassfilter in Reihe.
Die empirisch ermittelten Delay-Zeiten Kammfiltern und Allpassfiltern sind folgende (angegeben in Sampleanzahl für 44.1kHz ):
- Kammfilter 1: 1116
- Kammfilter 2: 1188
- Kammfilter 3: 1277
- Kammfilter 4: 1356
- Kammfilter 5: 1422
- Kammfilter 6: 1491
- Kammfilter 7: 1557
- Kammfilter 8: 1617
- Allpassfilter 1: 556
- Allpassfilter 2: 441
- Allpassfilter 3: 341
- Allpassfilter 4: 225
Implementierung
Die Implementierung des Reverbs an sich ist unkompliziert, da die eigentliche Signalverarbeitung in Kammfiltern und Allpassfiltern passiert. Hier passiert die Summierung und Routing der einzelnen Signale. Das Beispiel bezieht sich auf ein Mono-Kanal. Man kann es auf Stereo erweitern, wie im originalen Freeverb Effekt. Dafür werden beide Kanäle vorsummiert und auf beide Effektkanäle geschickt.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* Main process reverb */ float c_reverb::process(float x){ float y; y=0; //Feed the parallel comb filters unsigned i; for(i=0;i<n_comb;i++){ y+=comb[i].process(x); } //Pass through the serial allpass filters for(i=0;i<n_allpass;i++){ y=allpass[i].process(y); } //Attenuate output and mix wet& dry y=y*fixedgain*wetmix+x*drymix; return y; } |
Die Steuerung der Parameter Raumgröße, Dämpfung und Dry/Wet ist folgendermaßen implementiert.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
void c_reverb::set_wet(float* w){ //Update the dry&wet mix wetmix=*w*0.01; drymix=1-wetmix; } void c_reverb::set_size(float* s){ //Scale and set feedback parameter float feedback; feedback=(*s*0.01*scaleroom) + offsetroom; //Update the parameter of comb filters (Pointer on 2nd element: Roomsize) unsigned i; for(i=0;i<n_comb;i++){ comb[i].set_feedback(&feedback); } //Update the parameter of allpass filters (Pointer on 2nd element: Roomsize) for(i=0;i<n_allpass;i++){ allpass[i].set_feedback(&feedback); } } void c_reverb::set_damp(float* d){ //Scale and set damp float damp=*d*0.01*scaledamp; //Update the parameter of comb filters (Pointer on 2nd element: Roomsize) unsigned i; for(i=0;i<n_comb;i++){ comb[i].set_damp(&damp); } } |
Die empirisch ermittelten Parameter sind im Quellcode verfügbar.
Klangbeispiele
Anbei ist dieser Algorithmus mit ein paar verschiedenen Parametern zu hören.