GUI für SOX

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

@ 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
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

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
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

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
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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.
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

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
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.
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

aktuelle Version.
Mit den Objekten in der Liste war eine gute Idee. Neue Effekte lassen sich so recht schnell dazu programmieren.

Gruss, Seven
Antworten