CSCore - Highperformance Audiobibliothek

    • Release
    • Open Source

    Es gibt 589 Antworten in diesem Thema. Der letzte Beitrag () ist von simpelSoft.

      Erstmal freut mich das große Interesse an der Bibliothek :).
      Mangels Zeitgründen, kann ich dir das heute jedoch nicht mehr alles beantworten. Werde dir aber morgen gerne alle gestellten Fragen beantworten. Aber vorab mal soviel: Es ist alles möglich (oder zumindest etwas eingeschränkt möglich).
      1. Was genau verstehst du unter einer DeviceID? Je nach dem welche API du verwendest, hat DeviceID eine andere Bedeutung. Bei WaveIn ist das einfach ein Index der bei 0 beginnt. Bei Wasapi ist das ein Guid den kein Mensch lesen kann ;). Jedoch wird durch die ISoundIn Schnittstelle, das so abstrahiert, dass diese eine WaveFormat Eigenschaft hat (wird nach dem Initialisieren verfügbar), welche wiederum eine Channels Eigenschaft hat. Dort kannst du dann die Anzahl der Kanäle auslesen.
      2. Unter "tatsächlich" verstehst du (nehme ich mal an) sicherlich den Peak. Auch das ist möglich. Jedoch nicht direkt am SoundOut sondern durch eine Source. Das kommt jedoch auf exakt das gleiche raus. Ich hatte mal so eine Source, die das unterstützt hatte. Diese war jedoch veraltet und ich habe sie entfernt und bis jetzt nicht ersetzt (kann das aber morgen machen, da das so gut wie keine Arbeit ist).
      3. Dafür gibt es die die PanSource-Klasse: cscore.codeplex.com/SourceCont…Core/Streams/PanSource.cs. Dort einfach die Pan Eigenschaft verändern. 1 = nur links, -1 = nur rechts und 0 ist ausgeglichen. Dies funktioniert jedoch nur für Stereo-Streams. Falls du komplexere Streams hast mit 3 und mehr Kanälen, dann könnte man den DmoChannelResampler verwenden, welcher sowohl als Resampler dient als auch eine ChannelMatrix verwenden kann.
      4. Du startest ganz normal eine Aufnahme (jedoch ohne Eventhandler auf das DataAvailable-Event) sondern verwendest die SoundInSource. Dort gibst du beim Konstruktor die SoundIn-Schnittstelle der Aufnahme an (also z.B. die WasapiCapture- oder die WaveIn-Instanz) und diese SoundInSource, kannst du dann wiederum bei einem SoundOut wiedergeben.
        soundOut.Initialize(new SoundInSource(soundIn)); vereinfacht ausgedrückt. soundOut und soundIn müssen jeweils initialisiert und gestartet werden. Jedoch MUSS das soundIn initialisiert werden bevor eine SoundInSource Instanz damit erzeugt wird.
      5. Gab vor längerer Zeit mal einen Thread über dieses Thema: [VB.NET] Systemlautstärke auslesen und ändern

      Die restlichen Fragen kommen dann morgen :).


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
      Danke für deine Unterstützung.
      1. Ja. Ich habe die Device ID des WaveIn Device und möchte davon die Anzahl der Channel auslesen. Damit kann ich dann bei New WaveInEvent(New WaveFormat(44100, 16, [Anzahl der Channels])) die korrekte Anzahl der Channels ausgeben, es könnten ja auch mehr oder weniger als 2 sein.
      2. Ja, dann eben Source :) Du musst wegen mir keinen extra Aufwand betreiben, ich will ja nur die wichtigsten Funktionen dokumentieren, und wenn es nicht in der Auf NuGet erhältlichen Libary integriert ist, dann macht es ja auch kein Sinn, das zu Dokumentieren.
      3. Eigentlich habe ich nur mit Stereo gearbeitet. Wusste gar nicht, das es auch mit mehr Channeln möglich ist. Werde ich mir mal anschauen.
      4. und 5. schaue ich mir auch morgen erst an.
      Danke für deine Hilfe. Bin schon auf den Rest gespannt :D
      Liebe Grüße
      sothere
      1. Schau dir mal WaveIn.Devices an. Dort einfach die Channels Eigenschaft verwenden.
      2. Keine Sorge. Hab das so oder so schon lange in der Todo-Liste.
      3. Ist unüblich aber theoretisch möglich.

      Jetzt noch zu 6 und 7 von gestern:

      6.) Du kannst die Url einfach der CodecFactory übergeben (bei der Überladung mit Uri). CodecFactory.GetCodec(new Uri("StreamURL")) Bekommen tust du entweder die Source, welche du abspielen kannst oder eine NotSupportedException (falls das Streamformat nicht unterstützt wird).
      7.) Das SoundOut direkt kannst du nicht verstärken. Jedoch kannst du die GainSource verwenden: cscore.codeplex.com/SourceCont…ore/Streams/GainSource.cs

      Ach ja: Wenn dir Vista und höher auch reicht, dann würde ich zu WasapiCapture raten. Wasapi ist da einfach moderner und auch stabiler. WaveIn ist halt so ne Erfindung von Microsoft die langsam einfach in die Jahre kommt und mit Vista eigentlich abgelöst wurde.


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.

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

      Huhu, ich bins mal wieder. :P

      Vielleicht hast dus schon gesehen, [C#] Lissajous-Figuren Zeichnen, jedenfalls möchte ich mit deiner Lib Frequenzen rausfiltern, um diese dann grafisch darzustellen (dieser Teil ist schon fertig). Dazu hätte ich eine Frage und ein Problem, zuerst mal zur Frage:
      Ich brauche immer genau eine einzige Frequenz, funktioniert das mit der Fouriertransformation aus der Lib?
      Und das Problem ist, ich möchte verschiedene Eingangsquellen zulassen, genauer gesagt 1. Aufnahmegeräte (Mikrofone, Stereomix usw.), 2. Audio-Dateien und 3. konstante Frequenzen. Wie ich alles einzeln herbekomme, konnte ich mir zusammenreimen, Aufnahmegeräte mit MMDeviceEnumerator holen, Audio-Dateien einfach wie im Beispiel auf Seite 1 und konstante Frequenzen krieg ich mit dem Sinus-Generator. Allerdings bekomme ich da immer ein anderes Interface zurück, die auch scheinbar kein gemeinsames Basis-Interface haben, weshalb ich damit jetzt nicht wirklich was anzufangen weiß.
      Ja. Du kannst Frequenzen aus dem Signal rausfiltern (zumindest Frequenzbänder -> Genauigkeit hängt von Anzahl der Frequenzbänder ab).
      Was die verschiedenen Eingangssignale angeht:
      Mikro: IWaveSource source = new SoundInSource(soundIn);
      Datei: IWaveSource source = CodecFactory.GetCodec("datei.mp3");
      Sinus: IWavesource source = new SineSource(...).ToWaveSource(16);


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
      Das sind die Daten aus ner FourierTransformation. Ist nen Array von komplexen Zahlen mit größe 2^n. Hier ist nen Beispiel bei ner Visualisierung: CSCore Visualisierungs Tests (GDI+).zip. Ist zwar ne Visualisierung, jedoch lässt sich das Konzept übertragen. Und du hast dort auch Methoden wie du z.B. von ner Frequenz auf das Frequenzband kommst etc.

      Beispiel basiert auf dem Code von wpfsvl.codeplex.com/


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
      Sorry, aber ich verstehts nicht. :P Ich weiß nicht, was ne FourierTransformation macht.
      Brauche ich die BasicSpectumProvider-Klasse? Ich will will doch einfach nur die Frequenzen in Herz, dafür kann doch kein 400-Zeilen-Code erforderlich sein.
      Also schau: Du bekommst nicht exakt die Frequenz zurück. Du bekommst Frequenzbänder zurück. Du hast ein ganzes Frequenzspektrum welches du in n Bänder unterteilst. Bei unendlich Bändern, hast du eine unendliche Genauigkeit. Als Beispiel (nicht realitätsnahe): Du hast folgende Bänder:
      1-100Hz, 101-200Hz, 201-300Hz,...
      Jetzt willst du analysieren ob ne Frequenz bei 250Hz gibt. Das geht nicht. Du kannst nur eine Aussage treffen ob im 3. Frequenzband (also wo 250Hz einschließt) etwas vorhanden ist. Ob das dann 210Hz oder 290Hz sind, kannst du so nicht sagen. Nimmst du jedoch eine höhere Auflösung und hast von mir aus folgende Bänder: ...230-240;240-250;250-260;... dann kannste schon eher sagen ob es 245 gibt. Aber halt auch noch nicht genau. Aber immerhin.

      Was die Implementierung angeht: Du kannst ganz normal den FFTAggregator verwenden, dort das Event verwenden und dadurch wirste mit Daten versorgt (sei der aber bewusst, dass dieses Event aus dem Puffer-Thread gefeuert wird -> wenn du da lange was mit machst (z.b. etwas zeichnest), dann hört man das recht schnell mal). Du kannst dann folgenden Code verwenden:

      Quellcode

      1. public int GetFFTBandIndex(float frequency)
      2. {
      3. double f = _sampleRate / 2.0;
      4. return (int)((frequency / f) * ((int)_fftSize / 2));
      5. }



      Um den Index des Frequenzbandes herauszufinden in welchem deine Frequenz liegt. Zweites Beispiel von oben: Du willst Frequenz 245 -> ist in Frequenzband 2 (240-250Hz) -> Index 1.
      So dann haste den Index des Bandes. Dadurch bekommste ne komplexe Zahl. Die musste jetzt in etwas umrechnen mit dem man etwas anfangen kann.
      Da kannste in dem Beispielprojekt recht gut nachschauen. Du hast also die Komplexe Zahl Complex complex = .... Ohne irgendwas zu skalieren nimmst du einfach complex.Value. Je nach Anwendungszweck, kann man das dann noch entsprechend skalieren,... (z.B. bei ner Visualisierung, sieht es besser aus, wenn du das noch skalierst -> siehe SpectrumBase.cs):
      Spoiler anzeigen

      Quellcode

      1. switch (ScalingStrategy)
      2. {
      3. case ScalingStrategy.Decibel:
      4. value0 = (((20 * Math.Log10((double)fftBuffer[i])) - MinDBValue) / DBScale) * actualMaxValue;
      5. break;
      6. case ScalingStrategy.Linear:
      7. value0 = (fftBuffer[i] * ScaleFactorLinear) * actualMaxValue;
      8. break;
      9. case ScalingStrategy.Sqrt:
      10. value0 = ((Math.Sqrt(fftBuffer[i])) * ScaleFactorSqr) * actualMaxValue;
      11. break;
      12. }


      Aber wie gesagt. Ich weiß nicht genau was du jetzt machst und von dem her musste da einfach ma selbst schauen. Das liegt dann an dir. Biste mathematisch eh wesentlich begabter als ich ;).


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
      Ich will das umgekehrte machen.
      Du kannst dir das in etwa so vorstellen:
      Schließe ein Mikrofon an ein Oszilloskop an und nehme irgend was beliebiges auf (es kann ein einfacher Ton sein, es kann aber auch sehr komplex, z.B. Musik, sein). Das Oszilloskop stellst du aber nicht so ein, dass nach rechts die Zeit und nach oben der Ausschlag angezeigt wird, sondern das der Laser einfach nur mit dem Signal hoch und runter springt. Wäre deine Eingangsfrequenz also konstant 1Hz, dann würde der Laser genau einmal pro Sekunde hoch und runter gehen. Das selbe machst du jetzt mit nem zweiten Eingangssignal, aber dieses bewegt den Laser nach links und rechts. Es wird eine Figur entstehen, eine sog. Lissajous-Figur, welche bei Frequenzen, die zueinander harmonieren, recht schön anzusehen ist. Hier kannst du dir sowas mal ansehen, falls es dich interessiert:
      youtu.be/S_0JwgRo1H8?t=2m40s
      Die Anzeige ist schon fertig, siehe oben verlinkten Thread, und mit konstanten Frequenzen funktionierts einwandfrei. Ich will jetzt aber beliebige Eingangssignale zulassen, nicht nur konstante ausm "Frequenzgenerator". Ich müsste also irgendwie an die "Gesamtfrequenz" eines beliebigen Audio-Signales rankommen, also diejenige Frequenz, in der die Luft gerade tatsächlich schwingt (die Überlagerung aller Einzelfrequenzen).
      Also. Du bleibst bei der FFT. Du suchst dir das Band mit dem höchsten Wert und das ist dann die "Gesamtfrequenz". Ein anderer Weg fällt mir grad nicht ein. Bin auch kein Physiker.
      Die Frequenz des Bandes bekommst du mit folgender Formel:
      IndexDesBandes * SampleRate/AnzahlDerBänder
      Einheit ist in Hz.

      Kann dir jetzt auf die schnelle leider auch nicht mehr sagen. Wenn du jedoch sowas hin bekommst wie in dem Video dann... Respekt!


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
      Es funktioniert ... mehr oder weniger.
      Das Problem ist halt, dass die FFT nicht sonderlich genau ist, und wenn ich die Bandzahl zu hoch mache, dann dauert es einfach viel zu lange, bis was berechnet wurde, es soll ja aber möglichst schnell reagieren. Und dann kommt es halt, dass bei Frequenzen wie 400Hz:1200Hz, was eigentlich ein schön ruhiges Bild ergeben sollte, ein "Knäul" entsteht.

      Edit: mir ist gerde in den Sinn gekommen, vielleicht ist das ja auch einfach der falsche Ansatz. Anstatt mühsam irgendwo die Frequenz rauszuholen und daraus dann Punkte zu berechnen, kann ich mir ja auch einfach die Punkte direkt aus dem Audiosignal holen. Die X-Koordinate wäre die momentane Auslenkung der die Y-Kordinate die der 2. Eingangssignals. Ich bräuchte also nur nen Weg, wie ich die momentane Auslenkung eines Audiosignals auslesen kann. Ich hab nicht wirklich ne Ahnung davon, aber das sollte ich doch bei der Lib einfach aus dem Stream auslesen können, oder? Ich brauche einfach nur die momentane Auslenkung als Wert zwischen 0 und 1.

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

      Ganz so viele brauch ich nicht, aber nach meinen Tests braucht man schon ein paar tausend diskrete Punkte, damit auch bei hohen Frequenzen eine glatte Figur entsteht. Bei ner konstanten Frequenz von 1000Hz hab ich z.B. bisher ungefähr 5000 Punkte pro Sekunde berechnet (war auch notwendig).
      5000 Abtastwerte pro Sekunde? Ist das nicht etwas viel? Ist schon möglich aber naja. Nochmal: Ich spreche von Abtastwerten des Signals nicht von Punkten die du zeichnest.


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
      Ich will hier den Laser eines Oszilloskopes nachbilden, der reagiert eigentlich sofort. Ich stelle natürlich keine 5000FPS dar, das ist klar, aber ich muss trotzdem den Weg, den der Laser fahren würde, in der Zeit dazwischen mitberechnen.

      Edit: um das mal zu demonstrieren:
      Das hier ist das Bild, das entsteht, wenn ich die Frequenzen 100 und 400 zusammenmixe, bei es sind sogar 20000 Punkten (gerade nachgerechnet) pro Sekunde:

      So sieht es mit 500 Punkten pro Sekunde aus:

      Ich zeichne nur die Punkte aus den letzen 20 Millisekunden (damit wird die Nachleuchtzeit eines Oszilloskopes nachgebildet), es sind also wesentlich weniger als pro Sekunde berechnet.

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

      Also nochmal: Was genau brauchst du? 5000 Peaks pro Sekunde. Also die 5000 "höchsten" (also der Betrag der Samples) Werte einer Sekunde?


      Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.