Forum: PC-Programmierung Ist dieser Weg, um an die Daten der Soundkarte zu kommen, richtig?


von Bartosz B. (bartosz)


Angehängte Dateien:

Lesenswert?

Hallo,
Ich möchte an die Daten der Soundkarte gelangen und habe festgestellt, 
dass meine FFT soweit korrekt ist. Es muss einen Fehler in den 
Prozeduren geben, welche sich damit beschäftigen, an die Daten der 
Soundkarte zu gelangen.
Ist das richtig so?

VB.NET
1
Private Sub AudioDataAvailable(ByVal sender As Object, e As NAudio.Wave.WaveInEventArgs)
2
        bwp.AddSamples(e.Buffer, 0, e.BytesRecorded)
3
    End Sub
4
5
    Private Sub Start_Listening()
6
        Dim wi As New NAudio.Wave.WaveIn()
7
        wi.DeviceNumber = 1
8
        wi.WaveFormat = New NAudio.Wave.WaveFormat(Samplerate, 1)
9
        wi.BufferMilliseconds = CInt((CDbl(BufferSize) / CDbl(Samplerate) * 1000.0))
10
        usedMilliseconds = (CDbl(BufferSize) / CDbl(Samplerate) * 1000.0)
11
        AddHandler wi.DataAvailable, AddressOf AudioDataAvailable
12
        bwp = New NAudio.Wave.BufferedWaveProvider(wi.WaveFormat)
13
        bwp.BufferLength = BufferSize * 2
14
        bwp.DiscardOnBufferOverflow = True
15
16
        Try
17
            wi.StartRecording()
18
        Catch ex As NAudio.MmException
19
            MessageBox.Show($"Could not record from audio device!{NewLine}{NewLine}{ex.Message}",
20
                            "",
21
                            MessageBoxButtons.OK,
22
                            MessageBoxIcon.Error)
23
        End Try
24
    End Sub
25
26
    Public Sub getLatestData()
27
        Dim audioBytes As Byte() = New Byte(BufferSize - 1) {}
28
        bwp.Read(audioBytes, 0, BufferSize)
29
        If audioBytes.Length = 0 Then Return
30
        If audioBytes(BufferSize - 2) = 0 Then Return
31
        Dim BYTES_PER_POINT As Integer = 2
32
        Dim graphPointCount As Integer = audioBytes.Length \ BYTES_PER_POINT
33
34
        DataArray = New Double(graphPointCount - 1) {} ' added the -1
35
36
        For i As Integer = 0 To graphPointCount - 1
37
            DataArray(i) = CDbl(BitConverter.ToInt16(audioBytes, i * 2))
38
        Next
39
    End Sub

außerdem
1
''' <summary>
2
    ''' sample rate of the soundcard in Hertz
3
    ''' </summary>
4
    Private ReadOnly Samplerate As Integer = 48000
5
    Private ReadOnly BufferSize As Integer = CInt(Math.Pow(2, 10)) ' 1024
6
    Private bwp As NAudio.Wave.BufferedWaveProvider = Nothing
7
    ''' <summary>
8
    ''' 
9
    ''' </summary>
10
    Private usedMilliseconds As Double
11
    Private cnt As Integer = 0
12
    ''' <summary>
13
    ''' to hold the latest soundcard data which we will graph. <para></para>
14
    ''' Größe dieses Arrays wird BufferSize ÷ 2 , also 512.
15
    ''' </summary>
16
    Private DataArray As Double()

Beitrag #6915399 wurde von einem Moderator gelöscht.
von Bartosz B. (bartosz)


Lesenswert?

Ja, den Gedanken hatte ich auch schon. Nun bin ich aber zu 90% fertig. 
Das nächste mal mach ich ein Projekt mit C++. Mein Ernst.

von c-hater (Gast)


Lesenswert?

Bartosz B. schrieb:

> Ich möchte an die Daten der Soundkarte gelangen

Die grundsätzliche Frage ist hier: an welche genau? Die Eingabeseite 
(also Capture) ist trivial. Das kann man problemlos mit NAudios 
WaveIn-Zeugs erledigen. Man muss es einfach nur richtig benutzen. Wenn 
es bei dir nicht klappt, hast du was falsch gemacht. Ich bin zu faul, 
deinen Fehler zu suchen, kann dir aber sagen, dass das halt problemlos 
funktioniert, wenn man es richtig macht. Nur nötig ist NAudio nicht 
unbedingt. Man kann das auch auf niedrigerem Level (deutlich 
effizienter) machen.

Was etwas komplizierter ist, ist die Ausgabeseite, als der Scheiß, der 
normalerweise an den Lautsprechern oder Kopfhörern landet. Das 
abzufangen ist mit NAudio alleine nicht möglich. Spätestens hier muss 
man auf ein niedrigeres Level herabsteigen.

Ach so: Das ist in C++ alles kein bissel einfacher als in C#. Zwar muss 
man sich in C++ nicht mit dem Marshalling rumquälen, dafür aber selber 
dafür sorgen, dass speichertechnisch nichts schief geht. Marshalling 
zwingt dich förmlich dazu, es richtig zu machen, auf Fehler wirst du 
förmlich mit der blanken Faust in die Fresse aufmerksam gemacht.
C++ leistet das nicht. Die Folge sind oft "unerkärliche", schwer zu 
findende Fehler. C++ ist von Natur aus unsicher. Millionen 
Sicherheitslücken können nicht lügen.

von Jim M. (turboj)


Lesenswert?

Wirft folgende Zeile nicht im Mittel einen von 256 Audio Blöcken 
grundlos weg:
1
 If audioBytes(BufferSize - 2) = 0 Then Return

(Buffersize -2) ist doch ein Byte eines Audio Samples, und 0x0000 ist 
AFAIK ein gültiges Sample...


Außerdem sehe ich nicht wo im Code Stereo/Mono gesetzt wird ist.

Für solche Sachen gäbe es OBS, und IIRC kann man sich den Source Code 
auch anschauen. Allerdings ist der natürlich nicht in Basic.

von Bartosz B. (bartosz)


Lesenswert?

Hallo chater und  Jim M.,
danke für die Antworten.

Nochmal zum Problem: Laut Windows-EInstellungen macht die Soundkarte 
48000 Hz Samplerate und 3 Bytes. Wenn ich im Programm allerdings eine 
3 eingebe bei
1
Dim BYTES_PER_POINT As Integer = 2
 (und in der For-Schleife dann auch i * 3), kommt nur Unfug heraus. Also 
ich gehe davon aus, dass es doch nur 2 Bytes sind. Weil dann geht's 90% 
gut. Es scheint mir, als wenn selbst dann noch die im Programm 
deklarierte Sample-Rate nicht ganz korrekt ist.
Daher meine Frage.

@Jim: Stimmt, hast Recht, die Zeile lösche ich.

@chater:
>Das kann man problemlos mit NAudios WaveIn-Zeugs erledigen.

Ich mache das mit NAudio Waveİn.
Die Eingabeseite möchte ich haben.

von PittyJ (Gast)


Lesenswert?

c-hater schrieb:
> Ach so: Das ist in C++ alles kein bissel einfacher als in C#. Zwar muss
> man sich in C++ nicht mit dem Marshalling rumquälen, dafür aber selber
> dafür sorgen, dass speichertechnisch nichts schief geht. Marshalling
> zwingt dich förmlich dazu, es richtig zu machen, auf Fehler wirst du
> förmlich mit der blanken Faust in die Fresse aufmerksam gemacht.
> C++ leistet das nicht. Die Folge sind oft "unerkärliche", schwer zu
> findende Fehler. C++ ist von Natur aus unsicher. Millionen
> Sicherheitslücken können nicht lügen.

So ein Quatsch. Ich habe das in C++ vor 15 Jahren schon mal gemacht.
Mal in den alten Sourcen nachgeschaut: die eigentliche Leseroutine ist 
ca 100 Zeilen lang. Da ist nichts kompliziert. Es ging keine 
unerklärliche Fehler oder Sicherheitslücken.
Deine Aussage erinnert mich an die Fake-News, die es jetzt überall gibt.

von c-hater (Gast)


Lesenswert?

PittyJ schrieb:

> Deine Aussage erinnert mich an die Fake-News, die es jetzt überall gibt.

Ah ja? Und wie erklärst du dann die Existenz solcher Tools wie valgrind? 
Wenn die verschissene Sprache das selber leisten könnte, wären sie ja 
vollkommen überflüssig...

Die Existenz und Nutzung kann also nur als deutlicher Hinweis auf die 
Unvollkommenheit der Sprache gewertet werden. Alles andere wäre 
dramatisch unlogisch.

von c-hater (Gast)


Lesenswert?

Bartosz B. schrieb:

> Nochmal zum Problem: Laut Windows-EInstellungen macht die Soundkarte
> 48000 Hz Samplerate und 3 Bytes.

Ungünstig. Ich würde mal darauf tippen, dass das Format von NAudio 
schlicht nicht unterstützt wird. Kann bestimmt bloß "powers of two".

Ein Blick in die Quelltexte sollte das klarstellen. Sind ja immerhin 
problemlos verfügbar.

von Rolf M. (rmagnus)


Lesenswert?

PittyJ schrieb:
> So ein Quatsch. Ich habe das in C++ vor 15 Jahren schon mal gemacht.
> Mal in den alten Sourcen nachgeschaut: die eigentliche Leseroutine ist
> ca 100 Zeilen lang. Da ist nichts kompliziert. Es ging keine
> unerklärliche Fehler oder Sicherheitslücken.
> Deine Aussage erinnert mich an die Fake-News, die es jetzt überall gibt.

Seiner eigenen Logik nach wäre dann .net ebenfalls "von Natur aus 
unsicher", denn dessen Laufzeitumgebung ist wiederum in C++ und C 
implementiert.

von Schlaumaier (Gast)


Lesenswert?

Bartosz B. schrieb:
> Nochmal zum Problem: Laut Windows-EInstellungen macht die Soundkarte
> 48000 Hz Samplerate und 3 Bytes.

Ich würde die Windows-Einstellungen VERGESSEN.

Mache ich grundsätzlich immer. Einfach das Gerät (in den Fall die 
Soundkarte) richtig Initialisieren mit den Parameter die ich haben will 
und schon ist alles gut.

In Programmen wie Audacity o. Magix macht man das ja auch direkt und 
vergisst die Windows-Einstellungen.

Also setze die Parameter fest, oder frage sie ab und setzte sie dann.

Dann weißt du  auch das dir keiner dazwischen funkt.

Mein Rat.

von Bartosz B. (bartosz)


Lesenswert?

>Ich würde mal darauf tippen, dass das Format von NAudio
>schlicht nicht unterstützt wird. Kann bestimmt bloß "powers of two".

What? NAudio – als eingebundenes Paket – unterstützt das nicht? Dann 
weiß ich, wo die Abweichung herkommt. Danke :)

von Bartosz B. (bartosz)


Lesenswert?

Schlaumaier schrieb:
> Also setze die Parameter fest, oder frage sie ab und setzte sie dann.
>
> Dann weißt du  auch das dir keiner dazwischen funkt.
>
> Mein Rat.

Ich habe keinen Code gefunden, wie ich selbst die Parameter abfragen 
kann. Das klingt allerdings am besten.

von Bartosz B. (bartosz)


Lesenswert?

Ich dachte, das Problem kommt von generellen Abweichungen. In dem Sinne: 
wenn Windows gerade ne schlechte Sekunde hat, sind's eben nicht 48000 
Hz, sondern nur 47500 Hz.

von Schlaumaier (Gast)


Lesenswert?

Bartosz B. schrieb:
> Ich habe keinen Code gefunden, wie ich selbst die Parameter abfragen
> kann. Das klingt allerdings am besten.

Google mal nach der folgenden Include.

Microsoft.DirectX.DirectSound  <-

Hier mal ein alten VB Beispiel. Der Code dürfte aber leicht anzupassen 
sein.

https://www.codeproject.com/Articles/11184/The-ultimate-Managed-DirectSound-9-Tutorial-Part-1

Da es sich um einen DirektX Componente handelt.

Dazu noch folgende Infos

https://windll.com/de/dll/microsoft-corporation/microsoftdirectxdirectsoun

Lt. deren Seite ist das Win-10 u.f. kompatible.

So und nun musst du dich da nur noch schlau machen. Ich habe noch nie 
was audio-Mässiges selbst Programmiert deshalb ist das alles nur 
theoretische Recherche. Aber ich denke das die Infos für mich ausreichen 
würden um eine guten Anfang zu haben.

Besonders das Uralte VB Programm wäre mir eine große Hilfe damit ich 
weiß welche Parameter der DLL ich brauche. JAJA, ihr codet in C(++) aber 
das ist bei DLL völlig egal. Da der Aufruf nur unwesentlich abweicht. 
Ich übersetze c++ in VB im Kopf was so Sachen angeht. Muss ich weil es 
viele Code-Schnipsel nur in C gibt. ;)

von c-hater (Gast)


Lesenswert?

Schlaumaier schrieb:

> Google mal nach der folgenden Include.
>
> Microsoft.DirectX.DirectSound  <-

Ich würde eher empfehlen:

http://directshownet.sourceforge.net/

Das erspart allerdings natürlich "nur" die Deklarationsarbeit für .net.

Das grundsätzliche Konzept von DirectShow basiert auf dieser unsäglichen 
C++-(D)COM-Scheiße. Es führt also kein Weg daran vorbei, sich mit diesem 
grenzwertigen Software-Müll auseinanderzusetzen, den sich so nur völlig 
verbohrte C++-Freaks ausdenken konnten.
Fakt ist: wenn man das erfolgreich einsetzen will, muss man das Konzept 
und seine Funktionsweise verstehen. Und zwar ganz egal, ob man das 
direkt von C++ aus tut oder von einer .net-Sprache aus.

von Schlaumaier (Gast)


Lesenswert?

c-hater schrieb:
> Ich würde eher empfehlen:

Warum nicht ?

Dieses ganze DIREKT-Mist ist zickig ohne Ende.  Ist zwar sein seiner 
Erfindung besser geworden, aber GUT ist was ganz anderes.

Aber ich kenne halt für manche Probleme keine andere Lösung.

Beitrag #7038849 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.