Hallo,
für mein Program benötige ich eine verzögerungsfreie Soundausgabe, d.h. wenn ich meine „play“ funktion aufrufe muss sofort der Sound ertönen. Ich habe schon OpenAl und Alsa ausprobiert, aber ich habe jeweils eine kurze Verzögerung. Deswegen habe ich versucht, das ganze direkt auf der Soundkarte mit „/dev/dsp“auszugeben. Da ich auch mehrere Sounds gleichzeitig abspielen möchte, habe ich mir einen kleinen Soundserver geschrieben, allerdings habe ich wieder eine kleine Verzögerung. Hier mein Code:
unsigned int bufferSize = 100;
unsigned char* buffer;
buffer = new unsigned char[bufferSize];
std::vector<int> toDelete;
//sound server main loop while(true) {
//clear buffer for(unsigned int i = 0; i < bufferSize; i++) {
buffer[i] = 0;
}
//mix current playing files into buffer
std::vector<int>::iterator iter = _this->playing.begin();
_this->currPlaying = _this->playing.size();
while( iter != _this->playing.end() ) {
std::vector<int>::iterator it = _this->playing.begin();
while( it != _this->playing.end() ) {
if(*it == id) {
it = _this->playing.erase(it);
} else {
it++;
}
}
}
toDelete.clear();
}
delete[] buffer;
return 0;
}
void PlaybackDsp::mix(unsigned char* dest, unsigned int dest_size, unsigned char* src, unsigned int src_size, unsigned int src_pos, unsigned int src_length) {
unsigned int bufferSize = 100;
unsigned char* buffer;
buffer = new unsigned char[bufferSize];
std::vector<int> toDelete;
//sound server main loop while(true) {
//clear buffer for(unsigned int i = 0; i < bufferSize; i++) {
buffer[i] = 0;
}
//mix current playing files into buffer
std::vector<int>::iterator iter = _this->playing.begin();
_this->currPlaying = _this->playing.size();
while( iter != _this->playing.end() ) {
std::vector<int>::iterator it = _this->playing.begin();
while( it != _this->playing.end() ) {
if(*it == id) {
it = _this->playing.erase(it);
} else {
it++;
}
}
}
toDelete.clear();
}
delete[] buffer;
return 0;
}
void PlaybackDsp::mix(unsigned char* dest, unsigned int dest_size, unsigned char* src, unsigned int src_size, unsigned int src_pos, unsigned int src_length) {
unsigned int bufferSize = 100;
unsigned char* buffer;
buffer = new unsigned char[bufferSize];
std::vector<int> toDelete;
//sound server main loop while(true) {
//clear buffer for(unsigned int i = 0; i < bufferSize; i++) {
buffer[i] = 0;
}
//mix current playing files into buffer
std::vector<int>::iterator iter = _this->playing.begin();
_this->currPlaying = _this->playing.size();
while( iter != _this->playing.end() ) {
std::vector<int>::iterator it = _this->playing.begin();
while( it != _this->playing.end() ) {
if(*it == id) {
it = _this->playing.erase(it);
} else {
it++;
}
}
}
toDelete.clear();
}
delete[] buffer;
return 0;
}
void PlaybackDsp::mix(unsigned char* dest, unsigned int dest_size, unsigned char* src, unsigned int src_size, unsigned int src_pos, unsigned int src_length) {
for(unsigned int i = 0; i < length/2; i++) {
dest_s[i] += src_s[src_pos/2+i]/2;
}
dest = reinterpret_cast<unsigned char*>(src_s);
break;
}
}
}
Wie bekomme ich eine verzögerungsfreie Soundausgabe, oder mit welcher Bibliothek ist das möglich?
2. Frage:
Beim zusammenmixen von Sound halbiere ich zuerst die Amplitude um kein übersteuern der Sounds zu bekommen. Wenn ich jedoch mehrere habe, könnte es immer noch übersteuern, aber die Amplitude immer kleiner zu machen ist ja keine Lösung. Wie füge ich am besten die Sounds zusammen?
Mit freundlichen Grüßen
Lukas
Zuletzt bearbeitet von lakiday am 16:59:16 03.03.2010, insgesamt 1-mal bearbeitet
Wie hier schon erwähnt wurde, kannst du jackd nutzen. Das wäre wohl am einfachsten.
Je nach dem, was du vorhast, könntest du aber auch mit ALSA weiter kommen. Einfach mal den Puffer kleiner machen. Je kleiner der Puffer, um so geringer ist die Latenzzeit. Nichts anderes macht auch jackd. Wenn das dann noch nicht reicht, kannst du die Real-Time-Erweiterung der Kernels installieren. Die hilft dir aber nur etwas, wenn dein Puffer so klein ist, dass es zu underruns kommt.
Hallo,
danke für die bisherigen Antworten. Mit Jack bekomme ich nun eine verzögerungsfreie Ausgabe, allerdings bleibt Frage 2, wie ich das parallele Abspielen mehrerer Sound realisiere. Mein bisheriges Vorgehen:
1. Laden der Sounds mit libsnd
2. Ins richtige Format mit libsamplerate konvertieren
3. In meiner "play" Funktion füge ich den abzuspielenden Sound in meine play liste hinzu
4. Im Process Callback von Jack addiere ich nun die einzelnen Samples der Sounds
was denkt ihr von fließkommazahlen fürs mixen von sounddateien hab mal gehört das neuere bild/ton/video programme langsam umsteigen bzw. schon umgestiegen sind
Hallo,
Jack arbeitet mit floats. Wie überprüfe ich da auf ein Overflow und was wäre dann das sinnvollste? Einfach auf den maximal Wert setzen hört sich dann ja nicht sonderlich gut an.
Jetzt ist aber noch ein weiteres Problem aufgetreten. Wenn ich mehr als 7 sounds gleichzeitig abspiele benötigt mein Callback zu lange und Jack verwirft mein callback, sodass nichts mehr abgespielt wird. Wie kann ich mein callback noch optimieren?
Sollte ich das ganze mit normalen arrays realisieren und nicht std::map benutzen, oder gibt es da keinen großen Geschwindigkeitsunterschied?
Ich habe auch schon versucht die Buffer Größe von Jack zu verkleinern (momentan 1024) aber dann brauch mein callback immer zu lang.
Hallo,
Jack arbeitet mit floats. Wie überprüfe ich da auf ein Overflow und was wäre dann das sinnvollste? Einfach auf den maximal Wert setzen hört sich dann ja nicht sonderlich gut an.
Bei Floats limitiert man sich ja eh auf den Bereich -1.0f bis 1.0f. Du hast also keine Probleme mit potentiellen Overflows.
Zitat:
Sollte ich das ganze mit normalen arrays realisieren und nicht std::map benutzen, oder gibt es da keinen großen Geschwindigkeitsunterschied
Eine Map ist ziemlich aufwendig! Du solltest lieber std::unordered_map oder einen std::vector/std::array benutzen, wenn es geht.
Noch eine Anmerkung hierzu: Im JACK Process Callback ist genaugenommen alles tabu, was den Thread auf unbestimmte Zeit blockieren könnte. In dem von dir geposteten Code verstößt du an zwei Stellen gegen diese Regel:
C/C++ Code:
pthread_mutex_lock(&_this->mutex);
C/C++ Code:
pthread_mutex_lock(&_this->mutex);
C/C++ Code:
pthread_mutex_lock(&_this->mutex);
C/C++ Code:
_this->playing_offset.erase(iter->first);
C/C++ Code:
_this->playing_offset.erase(iter->first);
C/C++ Code:
_this->playing_offset.erase(iter->first);
Klar, der Code läuft trotzdem irgendwie, aber wenn er auch bei niedriger Latenz wirklich zuverlässig und ohne Aussetzer funktionieren soll, solltest du auf solche Dinge achten und die Laufzeit so deterministisch wie möglich halten. Wenn dein Callback zu lange braucht, wartet die Soundkarte schließlich vergeblich auf neue Daten. Und das betrifft ggf. nicht nur dein eigenes Programm, sondern auch andere, "unschuldige" JACK-Clients die gleichzeitig laufen und durch die Verzögerung nicht mehr rechtzeitig zum Zuge kommen.
Nächstes Thema anzeigen Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben. Sie können auf Beiträge in diesem Forum antworten. Sie können Ihre Beiträge in diesem Forum nicht bearbeiten. Sie können Ihre Beiträge in diesem Forum nicht löschen. Sie können an Umfragen in diesem Forum nicht mitmachen.
c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums
für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de
Werbekostenerstattung verdient werden kann.
Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de
enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt
(vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in
privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden.
Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere
übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.