Seite 2 von 2

Verfasst: Sonntag 13. Mai 2007, 23:39
von snakeseven
@ thelittlebug: Also die handelsüblichen Kompressoren arbeiten nach dem Threshold, Ratio, Attack und Release - Prinzip, wie es hier beschrieben wird. Beim SOX-Kompressor reagieren Attack und Decay (= Release) genau entgegengesetzt, wie erwartet. Eine Ratio gibt es nicht. Über "in-dB1,out-dB1" ist nicht nur eine Veringerung, sondern auch eine Verstärkung des Ausgangs-Signals möglich. Der Befehl heißt "Compander". Ein Kompanderist aber was ganz Anderes :roll: Noisegate oder Downwardexpander sind mit dem SOX-Kompressor ebenfalls möglich. Der SOX-Kompressor arbeitet eher wie ein Hüllkurvengenerator. Probiers einfach aus. Es lassen sich damit durchaus kompressorartige Effekte herstellen, man muß nur ein wenig umdenken.

FFT geht auch recht fix mit tkSnack, inkl. grafischer Darstellung.

@BackJack: So isses (fast). Keine gleichmäßige Pegelabsenkung. Der Verstärkungseffekt tritt durch das Output-Gain auf, was aber nichts anderes als ein nachgeschalteter Aufholverstärker und auch nicht immer vorhanden ist.

Ansonsten gibt es hier eine weitere Version, wo jeder Effekt sein eigenes Klassen-Objekt hat.

Gruss, Seven

Verfasst: Montag 14. Mai 2007, 18:19
von Leonidas
snakeseven hat geschrieben:Ansonsten gibt es hier eine weitere Version, wo jeder Effekt sein eigenes Klassen-Objekt hat.
Jetzt musst du dir noch abgewöhnen Module mit *-Importen reinzuziehen, siehe [wiki]Import[/wiki].
Achja und,

Code: Alles auswählen

# ---------------------------------------------------------------------------- GLOBALS ------------------------------------------------------------------------------------
sollte auch weg - es nervt unfassbar und ist auch noch Falsch. Sowas heißt nämlich nicht "Globals". Auch können Klassennamen mehr als drei Großbuchstaben enthalten - das fördert die Lesbarkeit enorm. PEP8 meint, dass man statt ``buildframe()`` besser ``build_frame()`` und statt ``setvalues()`` besser ``set_values()`` verwenden sollte. Außerdem sollten Kommentare über den Zeilen die man beschreibt stehen und nach daneben - fördert die Übersichtlichkeit und Hilft Zeilen kürzer als 79 Zeichen zu halten. Auch die ``call_volume()`` Funktionen sind allesammt kopiert und somit redundant. Man braucht nur eine generische Funktion, die alle Klassen abdeckt. Zur not kann man dann die anderen ``call_*()``-Funktionen per Lambda-Einzeiler wieder erstellen. Zuletzt ist es unnötig ``__init__()`` jemals explizit aufzurufen - das passiert automatisch wenn ein Objekt instanziiert wird.

Verfasst: Dienstag 15. Mai 2007, 18:50
von snakeseven
Hi Leonidas,
das hört sich nach einer sinnvollen Beschäftigung für ein verregnetes Himmelfahrt an :) Danke für die Verbesserungsvorschläge !

Gruss, Seven

Verfasst: Mittwoch 16. Mai 2007, 11:40
von snakeseven
Leonidas hat geschrieben: Auch die ``call_volume()`` Funktionen sind allesammt kopiert und somit redundant. Man braucht nur eine generische Funktion, die alle Klassen abdeckt.
Das Problem das ich dabei habe ist, daß man dem 'command=' Befehl der Buttons anscheinend keine Parameter übergeben kann, z.B. command = Play('Volume'). Wie können die einzelnen Aufrufe dann voneinander unterschieden werden ?
Zuletzt ist es unnötig ``__init__()`` jemals explizit aufzurufen - das passiert automatisch wenn ein Objekt instanziiert wird.
Hat bei mir nicht geklappt. Wenn ich den __init__() Aufruf in den call_effect() Funktionen weglasse, werden die Variablen nicht gesetzt ?

Gruss, Seven

Verfasst: Mittwoch 16. Mai 2007, 16:09
von Leonidas
snakeseven hat geschrieben:Das Problem das ich dabei habe ist, daß man dem 'command=' Befehl der Buttons anscheinend keine Parameter übergeben kann, z.B. command = Play('Volume'). Wie können die einzelnen Aufrufe dann voneinander unterschieden werden ?
Mit ``lambda``:

Code: Alles auswählen

command = lambda: Play('Volume')
Und das andere Problem kann nicht sein. Schreib dir mal in die Konstruktoren ein ``print`` rein - du wist sehen, dass dem Konstruieren eines Klassenobjekts der Konstruktor automatisch aufgerufen wird.

Verfasst: Mittwoch 16. Mai 2007, 16:26
von BlackJack
Wobei ich da jetzt schon wieder in `Play()` eine ``if``/``else``-Kaskade sehe. Wenn man sich die ganzen `call_*()`-Funktionen ansieht, dann ändert sich ja nur das Effekt-Objekt. Kann man also so verallgemeinern:

Code: Alles auswählen

def call_effect(effect):
    effect.__init__()  # Dubios!
    effect.build_frame()
    effect.set_values()
Und bei den Lambdafunktionen gibt man dann das Effekt-Objekt an:

Code: Alles auswählen

lambda: call_effect(VOL)
Wobei man bei der Namensgebung vielleicht die Klasse besser `Volume` und das Objekt `VOLUME` nennen sollte. Insgesamt ist die "Globalität" und Verflechtung in dem Programm immer noch extrem hoch.

Zu `__init__()` da gehört alles rein was bei der *Erzeugung* des Objekts passiert. Wenn mehrere Objekte in der `__init__()` dieselbe globale Variable setzen und Du die Objekte alle auf einen Schlag nacheinander erzeugst, dann "gewinnt" natürlich das zuletzt erzeugte Objekt.

Verfasst: Donnerstag 17. Mai 2007, 14:02
von snakeseven
Hi,
Lambda kannte ich noch nicht. Geht gut damit !
__init__ wird nur bei Programmstart ausgeführt, wenn ich die Objekte bilde (Effect = EFFECT()). Wenn ich die Effekte über call_effect(effect) wechsel, werden der Konstruktoren nicht aufgerufen und somit die globalen Variablen nicht gesetzt.

Ganz ohne globale Variablen kann ich es mir schwer vorstellen. Play() muß 'wissen', welcher Effekt gerade aktiv ist und den entsprechenden Kommando-String an SOX schicken.

Gruss, Seven

Verfasst: Donnerstag 17. Mai 2007, 15:38
von BlackJack
Alles was `play()` wissen muss, sollte als Argument übergeben werden. Ein Effekt-Objekt kennt alle seine Werte und sollte auch ein paar von den "globalen" Werten kennen, also könnte ein Effektobjekt auch eine `play()`-Methode bekommen. Von der Möglichkeit Argumente zu übergeben und Rückgabwerte zurückzugeben wird fast gar kein Gebrauch gemacht. Deswegen war die erste Variante selbst für ein rein prozedurales Programm stilistisch nicht besonders gut.

Du könntest den Effekten ein Namensattribut verpassen und die Objekte in eine Liste stecken. Dann kann man das Programm so umschreiben, dass der Name nur einmal im Programm stehen muss und die Buttons in einer Schleife erzeugt werden können.

In den `build_frame()`-Methoden ist viel sich wiederholender Quelltext, sowohl auf die Methode bezogen als auch in einzelnen Aufrufen in den Methoden. Da kann man sicher einiges herausziehen.

Verfasst: Freitag 18. Mai 2007, 11:38
von snakeseven
aktuelle Version.
Mit den Objekten in der Liste war eine gute Idee. Neue Effekte lassen sich so recht schnell dazu programmieren.

Gruss, Seven