Autor |
Beitrag |
Martok
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Mo 22.06.09 19:53
Hi!
Ich hab mich wohl doch etwas verschätzt mit meinem Projektchen, das geht doch nicht so einfach. Und zwar will ich Daten von n (n>0) Quellen zu m (m>0) Zielen durchleiten. Zwischendurch sollen Filter angewendet werden.
Mal ein wenig Ascii-Art, das ist so ziemlich der Extremfall. Da sieht man das Problem am Besten
1:1 ist aber genauso drin wie 1:2 oder 2:1 oder 42:23 etc..
Quelltext 1: 2: 3:
| Src 1 ---------\ /---- Sink 1 Filter Src 2 ---------/ \---- Sink 2 |
Das Problem kennt man ja aus der Schaltungssimulation... irgendwo liegt dann ein "Status" an, und damit macht man dann was. Ich hatte eigentlich vor, das ganze von den Sinks her aufzudröseln, aber da krieg ich dann Probleme weil die Sourcen mehrfach abgefragt werden.
Irgend eine art Pseudo-Uhr bräuchte man da, eine Zentrale Timestep-Geschichte klappt nicht so wirklich...
Da gibts doch bestimmt fertige Papers zu, oder? Nur ohne zu wissen wie das heißt, wirds eng... den Titel hier hab ich auch nur aus einer Checkbox in LTspice übersetzt
Grüße,
Sebastian
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
Thorsten83
      
Beiträge: 191
Erhaltene Danke: 1
|
Verfasst: Mo 22.06.09 21:25
Spontan hört sich das nach einem Observer an, um mal mit den Esoterikern zu sprechen 
|
|
Martok 
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 23.06.09 07:17
Hm, sagt nur wenig...
Ich hab das jetzt mal so gelöst, dass ein Controller... oh. Controller/Observer? ... jedenfalls, dass der alz einziger die Sourcen zum neu erzeugen veranlassen darf, und das global einmal pro Durchlauf tut. Erst sampeln alle Quellen neu, dann werden die Sinks gestartet und machen was damit. Zumindest einfach funktionierts:
Quelltext 1: 2:
| Sine Gen \---- L waveOut *--- R waveOut |
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 23.06.09 10:13
hmmm, bei Problemen mit nem Sink ist doch eigentlich eher der Klempner zuständig
Und nun zur spannenden Frage: Wie sieht das bzgl. der Daten aus? Wie muss man sich solch einen Filter vorstellen? Inwiefern sind die "Eingaben" der Quellen voneinander unabhängig? Wie setzen sich die Ausgaben für die Ziele zusammen? Gib bitte mal ein etwas ausführlicheres Beispiel.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Thorsten83
      
Beiträge: 191
Erhaltene Danke: 1
|
Verfasst: Di 23.06.09 10:20
Also ein Observer wäre in etwa so, dass sich die "Sinks"/Drains bei den Quellen anmelden.
Ändert sich nun was bei einer Quelle, so berichtet sie allen angeschlossenen Senken davon.
Die Frage ist halt, ob es das ist, was du brauchst 
|
|
Sinspin
      
Beiträge: 1335
Erhaltene Danke: 118
Win 10
RIO, CE, Lazarus
|
Verfasst: Di 23.06.09 11:49
Was hast du eigentlich genau vor? Was für Daten willst du verarbeiten (ich möchte jetzt nicht alle deine letzten Posts lesen um zu verstehen was du vorhast)
Aber, wenn ich dich richtig verstehe möchtest du eingespeiste und order virtuelle (Audio)signale über Filter (Operatoren) kombinieren wieder ausgeben und womöglich in weitere Operatoren einspeißen?
_________________ Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Warum sollte unser aller Mutter, die Natur, nicht die gleichen Rechte haben?
|
|
Martok 
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 23.06.09 14:04
Jop, werden (relativ kleine) Audiobuffer. Wobei dieser Thread hier noch eher Konzeptfrage war...
Thorsten83 hat folgendes geschrieben : | Also ein Observer wäre in etwa so, dass sich die "Sinks"/Drains bei den Quellen anmelden.
Ändert sich nun was bei einer Quelle, so berichtet sie allen angeschlossenen Senken davon. |
Ah, logisch.
Momentan ist mein Konzept genau andersrum: die Sink sagt "mach mir mal den Puffer voll", und die da dran konnektierte Einheit macht das. Dazu fordert sie ggf. von ihrer Quelle neue Daten an.
Das registrieren vorher wär zwar möglich, aber recht schwierig. Bei echtem wavein oder ähnlichem geht das noch, aber zum Beispiel ein Funktionsgenerator macht ja die Puffer "on-request" voll. Ansonsten müsste ich die noch per Thread oder so auf Echtzeit bringen...
Übrigens: Feedback ist im Moment ein ungelöstes Problem, weil das hier schon anklang.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Di 23.06.09 14:24
Naja, was bei Dir noch fehlt, ist eine "Mixer-Engine", d.h. du behandelst alle ein- und Ausgaben ersteinmal identisch behandelt werden. d.h. jeder Eingang wird getrennt behandelt und einzeln durch den Filter geleitet. diese gefilterten Daten werden dann an jedes Sink gereicht. In jeder Stufe gibt es nun hierbei eine Art Warteschlange, die die eingehenden Puffer hernimmt und verarbeitet:
Input:
- Generiert dynamisch Output-Blöcke; wartet ggf. wenn die Output-Queue voll ist.
Filter:
- Liest einen Block aus dem Input und schaut sich an, welche Geräte diesen haben wollen. Für jeden Sink wird der Filter einmal angewendet und für diesen in die Mixer-Queue gelegt
Mixer:
- Liest einen Block aus der FilterOutput-Queue und holt sich vom jeweiligen Sink den aktuellen Puffe für diesen Outputoffset. Nach einem Additiven Mischen (ggf. mit Skalierung) wird der Puffer zurückgeschrieben.
Sink:
- immer wenn ein Block als fertig markiert ist, wird dieser auf dem Zielgerät ausgegeben. Dies kann z.B. auch wieder ein Input-Gerät sein, was einfach mit einem gewissen Delay alle ausgegebenen Informationen wieder zurück in die Queue schleust.
Für die Datengenerierung wird dabei wie folgt verfahren:
- Takt-Anfang schreibt den aktuellen bei allen Eingabegeräten
- Jedes Eingabegerät wird nun gefragt, ob es Daten liefern möchte.
- Daraufhin sendet jedes Eingabegerät beliebig viele Puffer, jeweils mit einem Timecode (müssen unterschiedlich sein, damit Puffer hintereinander "angeordnet" werden)
- Für jeden Puffer, der geliefert wird, generiert der Filter die entsprechenden Ausgabe-Puffer unter beibehaltung von deren Timecode und zugabe des Ziel-Sinks.
- Der Mixer baut aus den gefilterten Puffern für jeden Sink den Ausgabepuffer zusammen.
- Wenn alle Input-Filter gemeldet haben, dass sie fertig sind mit der Generierung von Daten für diesen Zyklus, wird darauf gewartet, dass die Mixer-Queue leer ist. Zusätzliche Puffer mit höheren Timecodes werden hierbei als bearbeitet behandelt, und im derzeitigen Durchlauf ignoriert.
- Wenn alle Daten für den aktuellen Zyklus bearbeitet sind, werden diese an die jeweiligen Sinks geleitet und der nächste Zyklis gestartet.
Hoff mal, ich hab das jetzt soweit korrekt verstanden.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
Reinhard Kern
      
Beiträge: 591
Erhaltene Danke: 14
|
Verfasst: Di 23.06.09 15:15
Martok hat folgendes geschrieben : | Jop, werden (relativ kleine) Audiobuffer. Wobei dieser Thread hier noch eher Konzeptfrage war...
Momentan ist mein Konzept genau andersrum: die Sink sagt "mach mir mal den Puffer voll", und die da dran konnektierte Einheit macht das. Dazu fordert sie ggf. von ihrer Quelle neue Daten an.
Das registrieren vorher wär zwar möglich, aber recht schwierig. Bei echtem wavein oder ähnlichem geht das noch, aber zum Beispiel ein Funktionsgenerator macht ja die Puffer "on-request" voll. Ansonsten müsste ich die noch per Thread oder so auf Echtzeit bringen...
|
Hallo,
das hört sich zunächst völlig asynchron an, das kann es nicht sein. Alle Audiodaten müssen ein Zeitraster haben, z.B. 44.1 kHz bei CD, und dieses Zeitraster muss auch grundlegend für die Software sein. Die muss also 44100 mal pro Sekunde einen Wert bei den Quellen abholen. Wenn es unterschiedliche Zeitbasen gibt, wird das natürlich sehr komplex, aber es geht eben grundsätzlich nicht ohne Umrechnung von einer Zeitbasis auf die andere, also einer Art Normenwandlung. Die interne Zeitbasis sollte natürlich die schnellste sein, um Verluste zu vermeiden.
Gruss Reinhard
|
|
Martok 
      
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: Di 23.06.09 15:22
Innerhalb des Programms ist das Datenformat gleich. 16bit Signed, Samplerate 44100 normalerweise.
Verarbeitet werden immer Blöcke von (im Moment) 512 Samples, also ca. 11 Ms. Das ist meine Taktung momentan.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
|