Sound Frequenz Algorithmen

Design Patterns, Erklärungen zu Algorithmen, Optimierung, Softwarearchitektur
Forumsregeln
Wenn das Problem mit einer Programmiersprache direkt zusammenhängt, bitte HIER posten.
Antworten
Benutzeravatar
sirnoname
Beiträge: 67
Registriert: 20.06.2010, 11:04

Sound Frequenz Algorithmen

Beitrag von sirnoname »

Hallo,

ich möchte auf der Soundkarte eine Frequenz (Rechteck oder Sägezahn) ausgeben und dabei die Frequenz und die Amplitude verändern.
Hierzu habe ich ein Programm das mir nach Vorgabe eine Wav im Speicher erzeugt und dann wiederholend abspielt.
Die Frequenz und Amplitude verändert sich fortlaufend, also wird andauernd eine neue WAV erzeugt und das braucht CPU Load (alle 10 ms).
Nun will ich auf allen 8 Audio Ausgängen eine Frequenz haben, das schafft meine CPU nicht.
Wie macht man das normal, gibt es andere Wege? Wavetable und Midi möchte ich nicht gerne verwenden.

Grüße,
SirNoName
hagbard
Beiträge: 66
Registriert: 05.08.2010, 23:54

Re: Sound Frequenz Algorithmen

Beitrag von hagbard »

Die CPU ist hier weniger das Problem sondern eher die I/O. Alle 10ms einen neue Datei erzeugen ist selten eine gute Idee (falls ich dich richtig verstanden habe erzeugst du ständig wavfiles neu und spielst diese dann ab). Normalerweise solltest du eher kontinuierlich in einen Stream schreiben von der dann die Soundkarte liest. Dann sollten auch die 8 Kanäle nicht das Problem sein. Oder du schreibst halt in ein Quasi-Endlos-Wav-File (Sinnvollerweise nur bis zu einer bestimmten Größe dann fängtst du wieder am Anfang an) während dieses abgespielt wird.
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Sound Frequenz Algorithmen

Beitrag von antisteo »

Nimm doch eine Soundbibliothek, damit du nicht den Umweg über das Dateisystem und den Windows Media Player nehmen musst.
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
sirnoname
Beiträge: 67
Registriert: 20.06.2010, 11:04

Re: Sound Frequenz Algorithmen

Beitrag von sirnoname »

Hallo,

das mit der Wav habe ich wohl nicht gut ausgedrückt, diese wird im Speicher erzeugt. Also Daten die dann als wav der Karte übergeben werden. Mediaplayer ist nicht involviert, geht direkt an direct sound.

Welche Bibliothek würde so etwas machen? Also Frequenzen erzeugen und manipulieren wie bei einem Oszi?

Grüße,
sirnoname
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Sound Frequenz Algorithmen

Beitrag von antisteo »

Naja du musst die Sounds halt buffern und bekommst einen Callback immer, wenn der Puffer eine Mindestlänge unterschreitet. Je kleiner dieser Puffer ist, desto schneller reagiert dein Synti auf die Tastenanschläge. Ist der Puffer aber zu klein, kommt es zu Pufferunterläufen, was man dann als Knacken hört (der Rechner schiebt nicht schnell genug Soundsignale hinterher; das BS ist nicht echtzeitfähig)
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
sirnoname
Beiträge: 67
Registriert: 20.06.2010, 11:04

Re: Sound Frequenz Algorithmen

Beitrag von sirnoname »

Knacken ist egal, der Ausgang geht nicht an einen Lautsprecher. Es ist ein Frequenzgenerator.
Klar habe ich nichts gegen saubere Übergänge.
Wenn ich einen Rechteck Ton in das Wavetable schiebe kann dieses ja auch die Frequenz dehnen (Langsamer abspielen, Frequenz langsamer) und die Amplitude ändern (Lautstärke).
Das müsste doch auch ohne Wavetable gehen?
Ich will die Funktionen der Karte nutzen und nicht auf der CPU rechnen.
Benutzeravatar
ponx
Establishment
Beiträge: 217
Registriert: 04.05.2008, 12:52
Echter Name: Andy Ponx
Wohnort: Hamburg
Kontaktdaten:

Re: Sound Frequenz Algorithmen

Beitrag von ponx »

Also normalerweise verändert man die Ausgabe-Lautstärke und den Pitch (Abspiel-Geschwindigkeit) nicht ständig permanent in der WAV-Datei, sondern sagt der Hardware per Sound API des Betriebssystems, wie laut / schnell gerade welcher Puffer auf welchem Kanal abgespielt werden soll. In dem Fall reicht tatsächlich theoretisch nur eine einzelne Rechteck/Sägezahn-Schwingung im Puffer. Normalerweise hat die Sound API auch eine Funktion, um den zu Loopen, also den Puffer automatisch wieder von vorne abzuspielen, ohne dass man den Callback abfangen muss. Welche API benutzt du denn?
Was bei dir sehr wahrscheinlich die Performance killt, ist das ständige Neu-Allozieren von Speicher. Der ist nicht nötig in deinem Fall, solange du nix weiteres modulieren willst außer Lautstärke und Pitch. Falls doch, reichen zwei Puffer pro Kanal, die du ständig durchwechselst. Während der eine abgespielt wird, wird der neue mit neuen Daten gefüllt. Die Pufferlänge muss nur groß genug sein, sodass deine Hardware bzw API noch hinterherkommt, 500 ms sollten in jedem Fall reichen.
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Sound Frequenz Algorithmen

Beitrag von antisteo »

ponx hat geschrieben:Also normalerweise verändert man die Ausgabe-Lautstärke und den Pitch (Abspiel-Geschwindigkeit) nicht ständig permanent in der WAV-Datei, sondern sagt der Hardware per Sound API des Betriebssystems, wie laut / schnell gerade welcher Puffer auf welchem Kanal abgespielt werden soll. In dem Fall reicht tatsächlich theoretisch nur eine einzelne Rechteck/Sägezahn-Schwingung im Puffer. Normalerweise hat die Sound API auch eine Funktion, um den zu Loopen, also den Puffer automatisch wieder von vorne abzuspielen, ohne dass man den Callback abfangen muss. Welche API benutzt du denn?
Was bei dir sehr wahrscheinlich die Performance killt, ist das ständige Neu-Allozieren von Speicher. Der ist nicht nötig in deinem Fall, solange du nix weiteres modulieren willst außer Lautstärke und Pitch. Falls doch, reichen zwei Puffer pro Kanal, die du ständig durchwechselst. Während der eine abgespielt wird, wird der neue mit neuen Daten gefüllt. Die Pufferlänge muss nur groß genug sein, sodass deine Hardware bzw API noch hinterherkommt, 500 ms sollten in jedem Fall reichen.
Unsinn. 12 ms sollte man schon schaffen für ordentliche Musikproduktion. Und MIDI will kein Schwein mehr hören.
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
ponx
Establishment
Beiträge: 217
Registriert: 04.05.2008, 12:52
Echter Name: Andy Ponx
Wohnort: Hamburg
Kontaktdaten:

Re: Sound Frequenz Algorithmen

Beitrag von ponx »

antisteo hat geschrieben: Unsinn. 12 ms sollte man schon schaffen für ordentliche Musikproduktion. Und MIDI will kein Schwein mehr hören.
hatte ich nicht so verstanden, dass es um echte Musikproduktion ging, weil keine Lautsprecher an der Soundkarte hängen. 12 ms schafft man sicher mit ASIO Treibern, aber ich weiß ja nichtmal welche Sound API benutzt wird.
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Sound Frequenz Algorithmen

Beitrag von antisteo »

Also ich finde hörbare Buffer Underflows in jedem Fall inakzeptabel, egal, wie wenig professionell man sein will. Und Delays ab 300 ms sind auch ein Albtraum.
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
sirnoname
Beiträge: 67
Registriert: 20.06.2010, 11:04

Re: Sound Frequenz Algorithmen

Beitrag von sirnoname »

Hier mal die API Befehle und die Generatoren Funktionen.
Wie gesagt, suche was besseres, was von der Soundkarte gemacht wird.
Das untere ist gröstenteils geklaut, allerdings schon ein wenig optimiert.

Code: Alles auswählen

DirectSoundEnumerate((LPDSENUMCALLBACK)DSEnumCallback,NULL);
DirectSoundCreate8
initDirectSound

memArea createSineWave(unsigned int frequency) 
{ 
	memArea ma;
	int samples = 44100 / frequency;
	int i;
	ma.size = 2 * samples;
	ma.pointer = VirtualAlloc(NULL, ma.size, MEM_COMMIT, PAGE_READWRITE);
	if (ma.pointer != NULL) 
	{
		for (i = 0; i < samples; i++) 
		{
			*((short *) ma.pointer + i) = (short) (sin(((double) i / (double) samples) * 6.283185) * 32767.0);
		}
	}
	return ma;
}

void SetNewWave(unsigned int frequency, unsigned int volume)
{
	if(frequency==0)
	{
		if(status > 0){dsStop(currentsoundbuffer);}
		return;
	}
	VirtualFree(ma.pointer, ma.size, MEM_DECOMMIT);
	ma = createSineWave(frequency);
	int nextbuffer=0;
	if(currentsoundbuffer==0){nextbuffer=1;}
	if (ma.pointer != NULL) 
	{
		dsBufferCreated = createStaticBuffer(ma.size, volume, nextbuffer);
		if (dsBufferCreated)
		{
			dsBufferFilled = fillStaticBufferFromMem(ma.pointer, ma.size, nextbuffer);
			if (dsBufferFilled)
			{
				playStaticBuffer(nextbuffer);
				dsStop(currentsoundbuffer);
				status = 1;
				currentsoundbuffer=nextbuffer;
			}
		}
	} 
}
hagbard
Beiträge: 66
Registriert: 05.08.2010, 23:54

Re: Sound Frequenz Algorithmen

Beitrag von hagbard »

Du verwendest einen Buffer fester Größe den du jedes Mal neu erzeugts und abspielst. Statdessen solltest du einen Stream nehmen in dem du deine sich fortlaufenden sich ändernden Daten speicherst (Suchbegriff Streaming Buffers bei MSDN habe aber selber damit noch nichts gemacht). Ausserdem ezeugst du bei jeden Aufruf von SetWave den Buffer fest Größe immer wieder neu. Je nachdem wie effizient Konstruktor/Destruktor ist kann dass schon dein Performance-Lag sein...
Benutzeravatar
sirnoname
Beiträge: 67
Registriert: 20.06.2010, 11:04

Re: Sound Frequenz Algorithmen

Beitrag von sirnoname »

Wie kann ich das neue Erzeugen der Buffers verhindern?
Für streams habe ich keine Beispiele gefunden.
antisteo
Establishment
Beiträge: 854
Registriert: 15.10.2010, 09:26
Wohnort: Dresdem

Re: Sound Frequenz Algorithmen

Beitrag von antisteo »

Für DirectX kann ich es dir auch nicht erklären, aber du kannst mal schauen, wie das bei OpenAL gemacht wird: http://benbritten.com/2010/05/04/streaming-in-openal/
http://fedoraproject.org/ <-- freies Betriebssystem
http://launix.de <-- kompetente Firma
In allen Posts ist das imo und das afaik inbegriffen.
Benutzeravatar
FlorianB82
Beiträge: 70
Registriert: 18.11.2010, 05:08
Wohnort: Darmstadt
Kontaktdaten:

Re: Sound Frequenz Algorithmen

Beitrag von FlorianB82 »

Hier findest du die Informationen, wie du mit Streaming Buffes arbeitest.

Du erzeugst den Puffer dann nur einmal in ausreichender Größe (1 Sekunde Audiodaten sind mehr als ausreichend, eher weniger) und lässt diesen im Loop-Modus abspielen. Anhand der abfragbaren Position des Play-Cursors und des Write-Cursors weisst du dann, in welchem Bereich des Puffers alte schon abgespielte Daten liegen. Dann lässt du dir Zugriff auf diesen Pufferbereich mittles Lock() geben, und aktualiserst die Daten. Da du den/die Puffer in Software pollen und aktualisieren musst, bietet sich hierfür ein eigener Thread an.

Das ist im Normalfall (44100kHz, 16bit, mono) so performant, dass du keine nennenswerte Prozessorauslastung sehen solltest. Brauchst du zwei Ausgänge, dann nimm einen Stereopuffer. Brauchst du noch mehr Ausgänge, dann musst du für jeden (Stereo)-Ausgang ein eigenes Audio-Gerät initalisieren (also ein eigenes DirectSound-Objekt anlegen), und für dieses den Puffer anlegen. Sieh auch mal in die Systemsteuerung unter Audio, da siehst du ja, welche Ausgänge (Geräte) deine Soundkarte anbietet. Natürlich kannst du auch mehrere Soundkarten gleichzeitig nutzen, falls eine zuwenig Geräte anbietet. Bei 8 gewünschten Signalen = 4 Sterokanälen = 4 Geräten könnte das knapp werden mit nur einer Soundkarte, so man nicht im Besitz einer Recordingkarte ist, die gut und gerne mal 32 Stereo-Geräte anbietet.

Da du einen Freuenzgenerator baust, willst du sicherlich keine Resampling-Artefakte und ähnliches erhalten. Von daher würde ich dir raten, keine sekundären Puffer zu erstellen, sondern primäre. Dann kann zwar keine andere Windows-Anwendung über das mit dem jeweiligen Primärpuffer assoziierte Audiogerät etwas abspielen, aber genau das willst du vermutlich sowieso und vor allem werden deine Daten nicht mehr von der Windows Mixing-Engine konvertiert.
Benutzeravatar
FlorianB82
Beiträge: 70
Registriert: 18.11.2010, 05:08
Wohnort: Darmstadt
Kontaktdaten:

Re: Sound Frequenz Algorithmen

Beitrag von FlorianB82 »

Und? Wie hast du es jetzt umgesetzt?
Antworten