PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Marsyas



hirnfrei
10.07.2016, 00:10
Mahlzeit!

Ich hätte da mal wieder eine Frage, denn ich blicke irgendwie gerade so null durch!

Ich will Marsyas einsetzen. Installiert ist es, also das ist kein Problem. Doch wenn ich mir Hello World (http://marsyasweb.appspot.com/assets/docs/manual/marsyas-user/Hello-World-_0028playing-an-audio-file_0029.html#Hello-World-_0028playing-an-audio-file_0029) anschaue, dann kommt mir einiges Spanisch vor.



MarSystemManager mng;

MarSystem* playbacknet = mng.create("Series", "playbacknet");

playbacknet->addMarSystem(mng.create("SoundFileSource", "src"));
playbacknet->addMarSystem(mng.create("Gain", "gt"));
playbacknet->addMarSystem(mng.create("AudioSink", "dest"));

playbacknet->updctrl("SoundFileSource/src/mrs_string/filename", sfName);
playbacknet->updctrl("Gain/gt/mrs_real/gain", gain);
playbacknet->updctrl("AudioSink/dest/mrs_bool/initAudio", true);


Ich verstehe zwar prinzipiell, was da so passiert, nur die Art wie es passiert will sich mit nicht ganz erschliessen. Das kommt mir irgendwie ungewohnt vor! Wenn ich mir dann die Dokumentation anschaue wie zum Beispiel zu AudioSink (http://marsyas.info/doc/sourceDoc/html/classMarsyas_1_1AudioSink.html), dann sieht das auch wieder so seltsam und ungewohnt aus.



AudioSink (std::string name)
AudioSink (const AudioSink &a)
MarSystem * clone () const
void myProcess (realvec &in, realvec &out)
Processes data.
~AudioSink ()


zum Beispiel. Ich sehe es und in meinem Kopf bildet sich da einfach kein Bild zu. Als schaue ich mir Latein an. Ich sehe die Buchstaben, ich erkenne die Buchstaben, aber was ich da sehe ergibt keinen Sinn!

Wenn jetzt jemand sagt, das das irgendwie ganz hunds gewöhnliches C++ oder so ist, dann sollte ich dazu erklären, ich habe die meiste Zeit meines Programmierlebens in Ansi C geschrieben und bin eigentlich nur auf C++ weil es viele Dinge, wie das mit dem Speicherreservieren usw. einfach so viel einfacher macht. Ich bin da aber im grossen und Ganzen noch ziemliche Noob.

Auf jeden Fall bin ich um jeden Schubser in die richtige Richtung echt dankbar, denn langsam kann ich die Doku nicht mehr sehen und es frustriert einfach, wenn sich nichts bewegt.

botty
10.07.2016, 13:10
Dann wird's an der Zeit, dass Du Dir ein C++ Buch auf den Schreibtisch legst. Denn das Ganze benutzt die üblichen C++ Mechanismen - hier Polymorphie.

Der Manager hält intern eine Registry vor, in der stehen alle erlaubten Klassen, zu denen Objekte erzeugt werden dürfen. beim "create()" Aufruf prüft er ob er zu dem vereinfachten Klassennamen des ersten Parameters in der Registry ein Objekt zu diesem Typen hat und wenn ja, dann ruft es desen "clone()" Methode und reicht den Zeiger zum Aufrufer durch.
Das Wichtige an der Geschichte ist, das Serial, SoundFileSource, Gain, AudioSink alles Ableitungen der abstrakten Basisklasse MarSystem sind und die clone() Methode überschreiben und so im Manager Objekte der jeweiligen konkreten Klasse erzeugt werden, das "new" steht also in den clone()-Methoden.
Es ensteht so durch die vier create() Aufrufe ein Graph, wo das Objekt, auf das der Zeiger playbacknet drauf zeigt, vom Typ Serial aber der Zeiger nur vom Typ der Basisklasse MarSystem ist und drei Kinder mit ihren konkreten Typen hat.
Das entscheidende ist jetzt, dass die rein virtuelle Methode "myProcess()" in den abgeleiteten Klassen überschrieben werden muß und ist, denn da findet die spezielle Verarbeitung der Audiosamples statt.

Wenn du das Beispiel zu Ende anschaust wird dann das allgemeine MarSystem::tick() aufgerufen und dank Polymorphie wird innerhalb dieses Aufrufs das konkrete myProcess() der jeweiligen Objekte aufgerufen. Der Benutzer von playbacknet hat es so nur mit dem allgemeinen Fall zu tun und die konkreten Abläufe sind verborgen. Was Sinn und Sache des Ganzen Troubles ist.

Dieses updctrl dient dann dem Zugriff auf die Parameter der Objekte im Baum, sprich playbacknet weiß, wie es diese Pfade auflöst und dann auf die Attribute der Kindknoten zugreifen kann.

Gruß botty

hirnfrei
10.07.2016, 15:35
Das ist dann wohl einer der grösseren Unterschiede zu Ansi C ^^. Dann werde ich mir das mit dem Polymorphie mal anschauen. Vielen Dank schon einmal!

hirnfrei
11.07.2016, 19:11
Na wenn man sich das mit der Objektorientierung mal genauer anguckt (wie gut das es YT gibt ^^) dann macht das auf Einmal sogar Sinn ;). Da werde ich jetzt erst einmal meine bisherige diasound.hpp objektorientiert umbauen! Ich denke danach sollte ich es verstanden haben ;).

Ich sehe das in dem Beispiel also richtig, create kommt nicht von C++ sondern ist eine Methode von MarSystemManager. Ich baue also, grob ausgedrückt, mittels Create mehr oder minder eine eigene Klasse, bzw. Baue mit den Bausteinen aus MarSystemManager eine für meine Zwecke spezialisierte Klasse zusammen?

hirnfrei
12.07.2016, 21:32
Ich muss sagen, diese Objektorientierung ist in der Tat ziemlich cool. Hatte ich zuvor bei meinen Routinen für die Soundkarte immer das Problem, dass ich eine globale Variable als Zeiger für die initialisierte Soundkarte gebraucht habe, funktioniert das mit einer eigenen Klasse aber sowas von viel eleganter! Habe jetzt mein ganzes Programm für die Spracherkennung auf Objektorientierung umgestellt! Gefällt mir super gut.

Das mit Marsyas muss ich jetzt noch in den Griff bekommen.

botty
14.07.2016, 00:16
Cool,
wenn du dann noch alles in das Juces Framework (https://www.juce.com/) integrierst, bist du der nächste OOP Guru, "Have Fun".

HaWe
14.07.2016, 08:10
also ich bin da raus - OOP ist für mich die Hölle. Selbst in Java oder C#, wo alles noch sehr logisch und strukturiert ist.
Aber C++ ? nie und nimmer, eher geb ich mir die Kugel :mad:

Ich weiß, warum ich beim ANSI C bleibe: Klar und logisch und systematisch "straight".

hirnfrei
14.07.2016, 08:30
Bis vor einem Jahr hätte ich dir da noch mehr wie Recht gegeben, so ziemlich Alles was ich in Büchern und dem Netz zu OOP gelesen hatte hat mich mehr verwirrt wie informiert und wie zu Beginn dieses Threads ja zu sehen ist war das für mich ein Buch mit 70 Siegel.

Aber trotz Allem konnte ich mich dann vor rund einem Jahr C++ nicht mehr wirklich verwehren. Ich meine, nehmen wir mal Arrays. Bei C hat man da entweder ein statisches Array, oder muss erst für jeden neuen Eintrag Speicher reservieren. malloc, calloc, realloc, free. Peng irgendwo ein falscher Wert und das Programm ist futsch. Bei C++ baust du einfach das Array mit vector und hängst für jeden neuen Eintrag einfach ein push_back() dran. Keine Speicherreservierung usw. Es geht schneller und ist sicherer.

Und was OOP angeht. Hatte ich vor Kurzem noch das Problem mit globalen Variablen wegen der Soundkarte, so ist das jetzt Alles schön in eine Klasse verpackt. Da ist es jetzt wurst ob ich 1 oder 10 Soundkarten initialisiere. Das macht den Code um ein Vielfaches sauberer finde ich. Auch das Prinzip mit Public und Private finde ich sehr gut!

Letzten Endes muss aber jeder für sich die entsprechende Sprache finden. Vor einem Jahr habe ich mir da auch nicht rein reden lassen. Bin eben jetzt in die Richtung abgebogen und ziemlich zufrieden und da anscheinend der Unterschied zwischen C++ und Java nicht so gross ist wie zwischen C und Java nehme ich mal an, wenn ich mir irgendwann an Eclipse gewöhne geht auch die Entwicklung von Apps für Android los. Das habe ich schon einmal versucht, war aber letzten Endes eigentlich nur ein Abschreiben und rum kopieren von Code aus dem Netz ohne wirklich zu verstehen was ich da eigentlich mache ^^.

@botty:

Auf jeden Fall mal vielen Danke für den Schubser. Ein Guru werde ich aber mit Sicherheit nicht ^^. Aber auf jeden Fall verstehe ich jetzt langsam was bei dem Hello World von Marsyas da eigentlich passiert. Ich denke auch das ich das jetzt langsam mal anwenden kann ;). Sehe ich heute Abend ^^.

HaWe
14.07.2016, 08:35
ich habe OOP bereits vor knapp 20 Jahren probiert (Java, C++) und dann angeekelt zur Seite geschmissen.
Alles was mit OOP geht, geht auch mit ANSI C.
Wenn ich OOP sehe, muss ich mich schwer zusammenreißen, dass ich nicht kot**, das gilt schon fü Java und C#, erst recht aber für C++.

hirnfrei
14.07.2016, 08:54
Klar geht es auch in C. Wie gesagt, vor einem Jahr hätte ich dir noch voll zur Seite gestanden. Aber was mit C geht geht auch mit Assambler. Ist eben immer die Frage wie intensiv man Aufwand betreiben will und ich bin mittlerweile auf dem Punkt angelangt, dass ich lieber mein Projekt realisiere wie mich um Speicheraddressierung usw. zu kümmern und da kann ich nur sagen, durch C++ gibt es viel Code den ich nicht mehr schreiben muss weil die Klassen das erledigen.

Aber wie ich auch schon sagte, ich will hier niemand bekehren! Ich habe für mich jetzt OOP entdeckt und bin ziemlich Happy damit. Nicht mehr und nicht weniger.

HaWe
14.07.2016, 09:03
Schade, ich hätte gerne mit gemacht, auch mit FFT, Bandfiltern und Cross--Correlation, aber niemals mit C++.
Trotzdem viel Erfolg.


ps,
auch globale Variablen sind ja kein Thema, sie kommen einfach als globale Variablen in den lib-Header-File, oder man übergibt sie zwischen den lib-Funktionen als lokale Funktions-Parameter, fertig.

hirnfrei
14.07.2016, 09:24
Das Eine schliesst ja das Andere nicht aus! Da du ja meines Wissens nach auch mit g++ compilierst (oder hatte ich dich da falsch verstanden?) ist ja schnell ein Wrapper gebastetlt. Ob da hinten dran nun C++ steckt oder nicht muss dich ja nicht kümmern.

- - - Aktualisiert - - -

Globale Variablen an und für sich sind auch weniger das Thema. Allerdings war es bisher bei meiner Arbeit mit der Soundkarte so, da hatte ich diese eine Variable und die Funktionen haben dann immer genau auf diese Eine zugegriffen. Das macht die Sache ziemlich statisch. So umgebaut wie ich es jetzt habe gibt es da keine globalen Variablen mehr. Die Klasse hat diese Variable eingebaut. Mit jeder neuen Instanz der Klasse wird auch automatisch eine neue Variable gesetzt und letzten Endes kann ich dann, ohne im Code der hpp etwas zu verändern, 20 Soundkarten gleichzeitig betreiben wenn ich das will. Klar das ist unrealistisch. Aber nehmen wir mal an ich treibe meinen Bot an die Stelle, wo er nicht nur hören können soll sondern auch noch orten können soll von wo das Geräusch kommt. Dann brauche ich ja zwei Soundquellen die dann die Lautstärke vergleichen können muss. Da wären am Raspi ja zwei externe und die Interne zur Ausgabe der Antworten ja interesssant. Macht also drei Soundkarten von der zwei gleichzeitig aktiv sein müssen.

Klar, das kann man statisch natürlich genau so gut lösen. Aber so fühlt es sich für mich einfach besser an. Wie du sagst, siehst du OOP lässt du dir den Speiseplan des Tages noch einmal durch den Kopf gehen. Ich sehe OPP und finde es allerliebst.

So hat jeder Seins ;). Wie auch zB, du magst Windows, ich mag es nichtmal in der VirtualBox ^^.

HaWe
14.07.2016, 09:27
das ist sicher zuviel Aufwand, ich muss ja auch selber Zugriff auf wav files zum selber-öffnen und speichern eigener Sounds vom Micro haben, und damit fängt es ja schon an, wenn es keine arrays konstanter Länge sondern streams und strings und vectoren sind, und Arrays konstanter Länge müssen überall jederzeit greifbar und manipulierbar sein - doch mit den C++ Dingern kann ich komplett nichts anfangen, soweit waren wir ja schon mal.

Also bei C++ in diesen Libs bin ich komplett raus, sorry.

hirnfrei
14.07.2016, 10:25
Alles klar.

- - - Aktualisiert - - -

@botty

Ich habe aber mit der Doku zu Marsyas noch so meine Schwieirgkeiten, muss ich gestehen. Zwar verstehe ich jetzt, was in dem Beispiel Hello World da passiert, aber die Dokumentation und die Verweise auf die Dateien zu interpretieren fällt mir irgendwie etwas schwerer.

Wenn ich das richtig verstanden habe kann mir Energy die Energie/Lautstärke eines Signals ermitteln. Nur wo übergebe ich ihm dieses Signal? Da klemmt es irgendwie noch.

botty
15.07.2016, 13:57
Du, ich war nur über die Klassen drüber gegangen, um zu sehen wie die Objekte konstruiert werden. In der Tiefe kenne ich mich nicht mit diesem Framework aus.
Alledings ist in diesem Teil der Doku http://marsyas.info/doc/manual/marsyas-user/Architecture-concepts.html#Architecture-concepts
die Architektur erklärt und eine Klassenübersicht findest Du hier http://marsyas.info/doc/sourceDoc/html/hierarchy.html.

Das Ganze ist Datenflussorientiert, sprich Du hast immer Datenquellen am Anfang (AudioSource, SoundFileSource etc.). Dann kommen Prozessoren (Gain, NoiseGate etc) und zuletzt brauchst Du immer eine Senke (AudioSink, SoundFileSink) und du mußt diese Knoten in einer Serial oder Parallel einbetten. So sind die Netze immer aufgebaut.

In Bewegung wird das Ganze versetzt, indem tick() am äußerstem Knoten, der typischer Weise ein Serial ist, aufgerufen wird. Dann ruft Serial die Quelle auf, die eine Menge an Samples erzeugt und die werden dann an die darauffolgenden Knoten im Netz an die myProcess()-Methode weiter gereicht und dort verarbeitet, bis sie zum Schluß bei der Senke landen und dann geht das Ganze von Vorne los beim nächsten tick()-Aufruf.

Gruß botty

hirnfrei
15.07.2016, 15:21
Sieht ganz so aus als wäre das dann doch nicht das Richtige für mich. Ich will ja nur die vorhandenen Daten bearbeiten, sprich spezifische Werte davon haben usw. So wie ich das bis jetzt verstanden habe läuft da Alles über Marsyas und im besten Fall habe ich am Ende eine Datei. Hmm.