Mehrere Töne gleichzeitig abspielen

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 57 Antworten in diesem Thema. Der letzte Beitrag () ist von tron25.

    Ich habe jetzt die von dir genannte DLL in den Debug-Ordner kopiert. Wenn ich das Programm starte, höre ich kurz zwei Töne. Der Eine ca. bei 200 und der Andere bei etwa 1500 hz. Dann bekomme ich folgende Ausnahmebeschreibung:

    Assistent für verwaltetes Debuggen "NonComVisibleBaseClass" : "Ein QueryInterface-Aufruf wurde durchgeführt und die Klassenschnittstelle der für COM sichtbaren verwalteten "DataGridViewTextBoxCellAccessibleObject"-Klasse angefordert. Da diese Klasse aber von der für COM nicht sichtbaren "DataGridViewCellAccessibleObject"-Klasse abgeleitet ist, kann der QueryInterface-Aufruf nicht durchgeführt werden. Dies soll verhindern, dass die für COM nicht sichtbare Klasse von den COM-Versionsregeln eingeschränkt wird."
    sry, muss ich passen.
    das müsste man googeln. Da wäre die FehlerNummer auch wichtig, wenns die gibt.
    hier is was: learn.microsoft.com/de-de/dotn…oncomvisiblebaseclass-mda
    Aber komisch, weil DataGridViewTextBoxCellAccessibleObject ist ja nicht von mir, sondern ist FW-Bestandteil.

    vlt. sukzessive Teile ausbauen, bis der Fehler weg ist.
    Zu allererst im Designer die IsPlaying-Checkbox auf unchecked setzen, dann isser zum Startup still.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @tron25 Hier nochmal mein Beispiel per DirectSound ohne zusätzliche Verweise oder Fremd-DLLs. Da ich im Moment wenig Zeit habe, ist das nur auf die schnelle zusammen gebastelt und daher nicht zu 100% perfekt. Das zu perfektionieren überlasse ich Dir oder wem auch immer. :) Die Berechnung des Sinus ist auch nicht optimal. Hier müsste man eigentlich das ganze so berechnen, das immer ein vollständiger Sinus am Ende der Wave steht.

    Edit: Mir ist da gestern noch eine Idee durch den Kopf gegangen die ich selbst noch nicht probiert habe. Rein theoretisch reicht es aus einen SoundBuffer mit einer Frequenz von (DSBFREQUENCY_MAX - DSBFREQUENCY_MIN) / 2 zu erzeugen. Per IDirectSoundBuffer::SetFrequency kann man dann die gewünschte Frequenz, die zu hören sein soll, einstellen. Weitere SoundBuffer erstellt man dann vom diesem SoundBuffer per IDirectSound8::DuplicateSoundBuffer, stellt die gewünschte Frequenz ein usw.

    Anstelle den Sinus selbst zu berechnen, kann man auch eine Wave-Datei mit entsprechender Frequenz, zB. aus der Ressource, verwenden. Wave aus Ressource -> ByteArray -> WaveHeader für WAVEFORMATEX -> IDirectSoundBuffer::SetFormat auslesen und die restlichen Daten, hinter dem WaveHeader, in den SoundBuffer kopieren (IDirectSoundBuffer::Lock -> Marshal.Copy -> IDirectSoundBuffer::Unlock)
    Bilder
    • DirectSound.png

      5,27 kB, 875×207, 102 mal angesehen
    Dateien
    • DirectSound.zip

      (18,53 kB, 618 mal heruntergeladen, zuletzt: )
    Mfg -Franky-

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „-Franky-“ ()

    Wow, bis jetzt 78 mal heruntergeladen und keine Beschwerde das DirectSound eigentlich "deprecated" und der Nachfoger XAudio2 ist. :) Nicht das DirectSound jetzt plötzlich nicht mehr funktioniert. Das wird es noch lange nicht. Aber falls sich wer für XAudio2 interessiert, hier geht es zum Einstieg: learn.microsoft.com/en-us/wind…udio2/xaudio2-apis-portal Um das gleiche Ergebnis wie mit meinem DirectSound Code zu erreichen, ist gerade mal ein Interface in XAudio2 mehr zu programmieren.
    Mfg -Franky-
    So, jetzt habe ich die Oberfläche fertig. Es ist zwar etwas umständlich, aber ich habe für jeden Ton eine eigene Prozedur. Später, wenn alles funktioniert, werde ich einige zusammenfassen und kürzen.

    Da gibt es ein Problem, was ich nicht richtig verstehe. Die Funktion, die den Ton berechnet und ausgibt, soll sich die Frequenz und Lautstärke von den entsprechenden Schiebern holen. Allerdings funktioniert das nicht:

    VB.NET-Quellcode

    1. Private Function Links1TonErzeugen(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Integer
    2. 'einen puffer anlegen um Daten aus und in den Speicher zu kopieren
    3. Dim buff As Byte() = New Byte(length) {}
    4. 'die Daten aus dem Speicher in unseren Puffer kopieren, die Daten sind "stumm" weil nichts im Stream zum abspielen da ist
    5. Marshal.Copy(buffer, buff, 0, length)
    6. 'die einzelnen Samples erstellen, jedes Sample besteht aus 8 Bytes, je 2 Singles(2x 4 Bytes), je einmal für links und einmal für rechts
    7. For i As Integer = 0 To buff.Length - 9 Step 8
    8. 'Die folgende Zeile funktioniert nicht
    9. Dim Links As Single = CSng(Math.Sin(i / 8D * 2D * Math.PI * CDbl(Links1FrequenzSchieber.Value) / Samplingrate) * CDbl(Links1LautstaerkeSchieber.Value / 100))
    10. 'Die folgende Zeile funktioniert
    11. Dim Links As Single = CSng(Math.Sin(i / 8D * 2D * Math.PI * 500D / Samplingrate) * 0.2)
    12. Dim Rechts As Single = CSng(Math.Sin(i / 8D * 2D * Math.PI * 0 / Samplingrate) * 0)
    13. 'die bytes für den Puffer
    14. Dim LinksBytes As Byte() = BitConverter.GetBytes(Links)
    15. Dim RechtsBytes As Byte() = BitConverter.GetBytes(Rechts)
    16. 'die bytes in unseren Puffer kopieren
    17. Array.Copy(LinksBytes, 0, buff, i, 4)
    18. Array.Copy(RechtsBytes, 0, buff, i + 4, 4)
    19. Next
    20. 'die Daten aus unseren Puffer in den Speicher kopieren, damit sie nun abgespielt werden können.
    21. Marshal.Copy(buff, 0, buffer, length)
    22. Return length
    23. End Function


    Natürlich steht der Schieber für die Frequenz auf 500 und die Lautstärke auf 20 (20 / 100 = 0.2).

    Wie ihr seht, habe ich die entsprechenden Values in Double umkonvertieren lassen.

    Woran kann das noch liegen?
    Dateien
    • MultiBeep.zip

      (89,33 kB, 16 mal heruntergeladen, zuletzt: )
    Jou.
    @tron25 Dein Projekt ist nicht compilierbar.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @tron25 OK.
    Beschreib bitte mal, wie Dein Projekt bedient werden soll,
    was dabei passieren soll und was statt dessen passiert.
    ====
    Einige Button sind unter anderen Controls versteckt.
    ====
    Erstell Dir ein UserControl mit diesem Aussehen,
    da kannst Du alles erforderliche reinpacken und musst nichts indizieren oder n Mal hinschreiben.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    Die Buttons sollen später wegkommen, daher ist deren Position momentan für mich nicht wichtig. Leider kann ich auch diese PNG nicht erkennen. Ich weiß, dass das Erstellen einer GUI zeitaufwändig ist, aber ich mache mir die Mühe, weil ich dann Vieles, was für Blinde oder Sehbehinderte wichtig ist, selbst einstellen kann. Beispielsweise gibt es viele Programme, bei denen die Steuerelemente nicht korrekt indiziert sind. Mit Mausbedienung ist alles kein Problem, muß man aber mit der TAB-Taste navigieren, sollte die Indizierung passen. Außerdem kann ich auch so die Größe besser anpassen lassen.

    Die 5 oberen Gruppen sollen Töne mit bestimmten Frequenzen und Lautstärken für das linke Ohr und die Anderen für das rechte Ohr ausgeben. Damit sollen sich die genauen Frequenzen bei einem Tinnitus bestimmen lassen, um diesen terapieren zu können. Ich weiß natürlich, dass Tinnitus unterschiedliche Ursachen und Sympthome haben kann und dass nicht jede Art auf diese Weise behandelt werden kann. Dieser Weg funktioniert nach dem Prinzip der Komplementärfrequenzen. Beispielsweise könnte man sich einen Kopfhörer aufsetzen, das Programm starten und sein Profil laden. Dann schaut man sich einen Film an, während so nebenbei der Tinnitus im besten Fall ausgeblendet wird. Im Optimalfall reduziert sich der Tinnitus oder wird so wegtrainiert. Ich habe im Internet so ein paar solcher Programme gesehen. Allerdings gibt es bei denen zwei Punkte, die mich stören. Einerseit kann nur ein Ton ausgegeben werden und andererseits sind Webanwendungen für Menschen, die einen Screenreader verwenden nicht so gut zu bedienen.

    Bei meinem Programm soll es auch möglich sein, verschiedene Profile abzuspeichern, um diese dann schnell laden und auch verändern zu können.
    @tron25 Bau Dir ein UserControl, in dem alle erforderlichen Controls für ein Ohr für eine Frequenz vorhanden sind.
    Implementiere den Inhalt so, dass Du links / rechts als Property übergibst.
    Wenn das alles läuft (nicht vorher) ziehst Du 10 oder 12 oder mehr dieser Controls auf Deine GUI und implementierst den Rest.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo -Franky-,
    danke für dein Angebot, aber ich würde gerne mein Problem lösen, da ich schon einiges an Arbeit in die GUI gesteckt habe. Wie oben beschrieben, habe ich nur noch das Problem, dass nur ein Sound erzeugt wird, wenn ich eine Zahl anstatt einer Variablen in die Funktion einsetze. Wahrscheinlich ist das ein banaler Fehler, aber ich komme trotzdem nicht darauf.
    So, nun habe ich den Fehler gefunden, verstehe ihn aber nicht. Wenn ich die Frequenz aus dem Value des Schiebers für die Frequenz hole, stürzt das Programm ab. Nun habe ich eine globale Variable deklariert, in die bei jeder Änderung der Frequenz diese geschrieben wird. Die Funktion holt sich den Wert nun aus dieser Variablen und es funktioniert.

    Wie gesagt, verstehe ich aber nicht, warum? Ob ich den Wert aus dem Value eines Schiebers oder aus einer Variablen hole, dürfte doch egal sein, oder?

    Hier schicke ich euch das aktuelle Programm.
    Dateien
    • MultiBeep.zip

      (590,49 kB, 83 mal heruntergeladen, zuletzt: )