Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

11.09.2013, 09:46

C# Soundframework

Hallo zusammen.

Ich bin auf der Suche nach einem geeigneten Framework/Helper/Whatsoever um verschiedene Sounds parallel abspielen zu können. Aktuell bin ich mit keiner meiner gefundenen Lösungen zufrieden. Ich nutze C#/OpenTK in meinem Projekt.

Was ich bisher gefunden habe:
[System.Media.Soundplayer]
--- kann Sounds nicht parallel abspielen
[OpenAL (in OpenTK enthalten)]
--- nicht wirklich dokumentiert
--- wenn überhaupt gibt es alte Dokus, die alte Klassen (z.B. den AudioReader) verwenden. Diesen gibt es in neuen Versionen von OpenTK gar nicht mehr.
--- schmeißt mir andauernd OutOfMemory-Exceptions. Auf Grund fehlender Dokumentation habe ich bisher noch nicht herausgefunden, warum das so ist.
[DirectX]
--- nicht getestet
[Bass.NET]
--- kostenpflichtig
--- nicht getestet

Meine Fragen:
- Könnt ihr ein gutes Framework für Sound unter C# empfehlen?
- Kann ich DirectSound mit OpenTK kombinieren (das eine ist bekanntlich DirectX, das andere OpenGL)?
- Habt ihr ein funktionierendes (aktuelles!) Beispiel für das Abspielen von Sounds unter OpenAL oder ein gutes Tutorial?

Danke schonmal für eure Hilfe
Neph

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

2

11.09.2013, 10:21

Ich wüsste nicht, wo genau das Problem mit OpenAL sein sollte. Die Doku mag kein Tutorial sein, aber sie ist dennoch für mich immer ausreichend gewesen. Vor allem willst Du ja scheinbar nichts abgefahrenes machen, sondern einfach nur Sounds parallel abspielen. Und das ist echt kein Hexenwerk. Jedes Sound-File bekommt einen Buffer. Jeder abzuspielende Sound bekommt eine Source mit dem entsprechenden Buffer verknüpft. Sources abspielen und fertig. Du kannst mehrere Sources haben, die sich auf den selben Buffer beziehen und somit den selben Sound parallel abspielen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

3

11.09.2013, 10:27

Ich benutze unmanaged OpenAL und hab auf die unmanaged Klassen die ich gebaut hab noch nen .NET Wrapper draufgesetzt ...
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

11.09.2013, 10:34

So ähnlich ist das bei mir auch. Ich benutze unmanaged OpenAL aus eigenen managed C# Klassen heraus.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

5

11.09.2013, 13:49

Wenn du ohnehin bereits OpenTK verwendest, würde ich dir ganz klar zu OpenAL raten - das verwende ich auch (über die von OpenTK zur Verfügung gestellten Bindings) und hatte nie ernsthaft Probleme damit. Lediglich für die Unterstützung komprimierter Audioformate (beispielsweide Ogg Vorbis) musst du nochmal selbst nachrüsten, wofür sich eine externe Library anbieten würde. Falls du ein wenig Beispielcode sehen willst, kannst du gerne einen Blick in den Duality Source Code werfen - ist aber kein minimalistisches Beispiel, da dort bereits eine Menge zusätzlicher Kram draufgesetzt wurde.

6

11.09.2013, 13:50

Dann frage ich mal konkreter, wenn ihr euch auskennt.

Erst einmal, was ich meine, verstanden zu haben:

- Der Buffer muss für jedes Sound-File angelegt werden.
- Zum Abspielen binde ich einen Buffer an eine Source.
- Mehrere Buffer -> eine Source klappt nicht, bzw. er nimmt den ersten/letzten?
- Ein Buffer -> mehrere Sources spielt den selben Sound mehrfach ab.

=> D.h. ich brauche für jeden Sound-Kanal eine Source (z.B. eine Source für Musik, eine Source für Voice, etc.).

Wann muss ich die Buffer anlegen?
Kann ich die Buffer jederzeit anlegen oder muss ich diese zu einem früheren Zeitpunkt anlegen? Soll ich da bereits alle Sounds laden (auch die, die womöglich nie gebraucht werden, weil das entsprechene Event nicht stattfindet)?

Ich habe das mal eben getestet und kann den Sound abspielen, wenn ich den Sound inkl. Buffer und Source am Anfang erstelle (noch vor dem Main-Window). Wenn ich das gleiche zur Laufzeit des Spiels mache, kriege ich eine OutOfMemory-Exception. Leider ist mein Wissen zur Speicherverwaltung recht beschränkt.

Legend

Alter Hase

Beiträge: 731

Beruf: Softwareentwickler

  • Private Nachricht senden

7

11.09.2013, 13:57

Also mit unmanaged OpenAL ist es insbesondere für längere Sounds/Musikstücke möglich mit ein paar kleinen Buffern die Audiodaten nach und nach zu streamen. So muss man nicht alles auf einmal laden.

Und ja, für jeden Ton der abgespielt werden soll, brauchst du eine eigene Source, dass sehe ich auch so, bzw. benutze es so.
"Wir müssen uns auf unsere Kernkompetenzen konzentrieren!" - "Juhu, wir machen eine Farm auf!"

Netzwerkbibliothek von mir, C#, LGPL: https://sourceforge.net/projects/statetransmitt/

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

11.09.2013, 13:57

Out of Memory? Was zum Geier lädst du da?

Generell ist es, wie ich es schon gesagt habe:
- Es gibt Buffer, da kommen die Sounddaten rein - also da rein werden die Files gepackt - jedes File in einen Buffer (oder aufgesplittet in mehrere)
- Es gibt Sources, die angeben wo im Raum und mit welchen Eingenschaften eine Soundquelle existiert - also WIE sie es abzuspielen hat
- Jede Source referenziert einen Buffer, denn das beschreibt, WAS sie abzuspielen hat

Willst Du also mehrere des selben Sounds parallel, hast Du einen Buffer und mehrere Sources. Willst Du verschiedene Sounds parallel, hast Du mehrere Buffer und mehrere Sources.
Wann Du das lädst, ist Dir überlassen. Das kann beim Start des Spiels sein. Kann aber z.B. auch erst passieren, wenn ein Level geladen/gestartet wird. Kann aber auch sein, dass Du sie dynamisch laden willst, sobald Du sie brauchst. Letzteres kann allerdings Zeit brauchen und daher eine schlechte Idee sein.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

9

11.09.2013, 14:02

Dann frage ich mal konkreter, wenn ihr euch auskennt.

Erst einmal, was ich meine, verstanden zu haben:

- Der Buffer muss für jedes Sound-File angelegt werden.
- Zum Abspielen binde ich einen Buffer an eine Source.
- Mehrere Buffer -> eine Source klappt nicht, bzw. er nimmt den ersten/letzten?
- Ein Buffer -> mehrere Sources spielt den selben Sound mehrfach ab.

=> D.h. ich brauche für jeden Sound-Kanal eine Source (z.B. eine Source für Musik, eine Source für Voice, etc.).

Wann muss ich die Buffer anlegen?
Kann ich die Buffer jederzeit anlegen oder muss ich diese zu einem früheren Zeitpunkt anlegen? Soll ich da bereits alle Sounds laden (auch die, die womöglich nie gebraucht werden, weil das entsprechene Event nicht stattfindet)?

Ich habe das mal eben getestet und kann den Sound abspielen, wenn ich den Sound inkl. Buffer und Source am Anfang erstelle (noch vor dem Main-Window). Wenn ich das gleiche zur Laufzeit des Spiels mache, kriege ich eine OutOfMemory-Exception. Leider ist mein Wissen zur Speicherverwaltung recht beschränkt.


Ich glaube, du hast die Verwendung bzw. den Sinn und Zweck einer "Source" missverstanden. Eine Source ist nicht per se dafür gedacht, einen Kanal à la Musik, Voice oder Effekt abzubilden, sondern grundsätzlich erst einmal eine allgemeine Instanz zum Abspielen von Audiodaten. Sie kann dabei verschiedene Rollen übernehmen, beispielsweise das Abspielen eines einzelnen Buffers (Soundeffekt) oder aber auch das kontinuierliche Abspielen einer Buffer Queue (Streaming, beispielsweise Musik).

Wenn du einen Soundeffekt abspielen willst, ist deine Beschreibung schon mehr oder wengier korrekt: Erstmal beim Laden einen Buffer erzeugen und wenn du dann konkret was abspielen willst, diesen Buffer eienr Source zuweisen. Da eine Source auch attribute wie Lautstärke, Position im Raum, etc. verwaltet, kann es durchaus Sinn machen, mehrere Sources zu haben, die auf denselben Buffer verweisen; ein Sound kann ja durchaus mehrfach gleichzeitig abgespielt werden, an verschiedenen Positionen im Raum, zeitversetzt, mit verschiedenen Parametern.

Für das Abspielen von Musik und größeren Audiodaten würde ich dringend von dieser Methode abraten, da ein unkomprimiertes Musikstück schonmal 10 MB / Minute benötigen kann - so viel Speicher willst du sicher nicht permanent für Audio reservieren. Stattdessen solltest du hier eher den Weg über Streaming gehen, wo du eine einzelne Source für das Abspielen eines Songs nutzt, der du nach und nach immer neue Buffer per Queue-Befehl "hinten anfügst" während du die bereits verarbeiteten Buffer "vorne wieder wegnimmst". Eine Art Ringbuffer mit einer handvoll kleiner Buffer Objekte reicht da eigentlich schon, aber um einen eigenen Thread fürs Streaming wirst du wohl nicht herumkommen.

10

11.09.2013, 14:03

Ok, das habe ich soweit verstanden. Dann versuche ich heute abend nochmal, das Ganze so umzusetzen. Duality-SourceCode scheint (mal wieder) ein guter Ansatz zu sein. Wenn das dann immer noch nicht geht, komme ich nochmal konkret mit meinem Problem + Codebeispiel.

Werbeanzeige