Stereomix-Aufnahme per NAudio

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von TheChosen0ne.

    Stereomix-Aufnahme per NAudio

    Hey zusammen.
    Ich schreibe momentan ein Programm welches mir bei meiner "Musikverwaltung" hilft.

    Eine Funktion ist, dass der Systemsound aufgenommen wird; Nach Recherchen im Internet, wurde dafür die API NAudio empfohlen, auch hier. Allerdings komme ich nicht wirklich damit zurecht. Ich habe mir die vom Macher erstellten Tutorials zur Implementierung dieser Funktion durchgelesen. Am Ende habe ich praktisch den vorgegebenen C#-Quellcode durch nen Converter gepackt, und dabei die restlichen noch in VB angezeigten Fehler selbst "behoben". Eigentlich sollte das Ganze ziemlich gut übersetzt worden sein, allerdings hier nochmal die vorgegebenen Quelltexte und die dazugehörigen Übersetzungen von mir in VB.NET:
    Spoiler anzeigen

    Übersetzung von mark-dot-net.blogspot.de/2009/…ard-output-to-wav-in.html:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class WaveRecorder
    2. Implements NAudio.Wave.IWaveProvider, IDisposable
    3. Private writer As NAudio.Wave.WaveFileWriter
    4. Private source As NAudio.Wave.IWaveProvider
    5. Public Sub New(pSource As NAudio.Wave.IWaveProvider, pDestination As String)
    6. MyBase.New
    7. source = pSource
    8. writer = New NAudio.Wave.WaveFileWriter(pDestination, Me.source.WaveFormat)
    9. End Sub
    10. Public Function Read(ByVal buffer() As Byte, ByVal offset As Integer, ByVal count As Integer) As Integer Implements NAudio.Wave.IWaveProvider.Read
    11. Dim bytesRead As Integer = Me.source.Read(buffer, offset, count)
    12. writer.Write(buffer, offset, count)
    13. Return bytesRead
    14. End Function
    15. Public ReadOnly Property WaveFormat As NAudio.Wave.WaveFormat Implements NAudio.Wave.IWaveProvider.WaveFormat
    16. Get
    17. Return Me.source.WaveFormat
    18. End Get
    19. End Property
    20. Public Sub Dispose() Implements IDisposable.Dispose
    21. If (Not (Me.writer) Is Nothing) Then
    22. Me.writer.Dispose()
    23. Me.writer = Nothing
    24. End If
    25. End Sub
    26. End Class


    Übersetzungen von mark-dot-net.blogspot.de/2009/…-sine-wave-in-naudio.html:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public MustInherit Class WaveProvider32
    2. Implements NAudio.Wave.IWaveProvider
    3. Private daswaveFormat As NAudio.Wave.WaveFormat
    4. Public Sub New()
    5. Me.New(44100, 1)
    6. End Sub
    7. Public Sub New(ByVal sampleRate As Integer, ByVal channels As Integer)
    8. MyBase.New
    9. Me.SetWaveFormat(sampleRate, channels)
    10. End Sub
    11. Public Sub SetWaveFormat(ByVal sampleRate As Integer, ByVal channels As Integer)
    12. Me.daswaveFormat = NAudio.Wave.WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channels)
    13. End Sub
    14. Public Overloads Function Read(ByVal buffer() As Byte, ByVal offset As Integer, ByVal count As Integer) As Integer Implements NAudio.Wave.IWaveProvider.Read
    15. Dim waveBuffer As NAudio.Wave.WaveBuffer = New NAudio.Wave.WaveBuffer(buffer)
    16. Dim samplesRequired As Integer = (count / 4)
    17. Dim samplesRead As Integer = Me.Read(waveBuffer.FloatBuffer, (offset / 4), samplesRequired)
    18. Return (samplesRead * 4)
    19. End Function
    20. Public MustOverride Overloads Function Read(ByVal buffer() As Single, ByVal offset As Integer, ByVal sampleCount As Integer) As Integer
    21. Public ReadOnly Property waveFormat As NAudio.Wave.WaveFormat Implements NAudio.Wave.IWaveProvider.WaveFormat
    22. Get
    23. Return Me.daswaveFormat
    24. End Get
    25. End Property
    26. End Class


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class SineWaveProvider32
    2. Inherits WaveProvider32
    3. Private sample As Integer
    4. Public Sub New()
    5. MyBase.New
    6. Frequency = 1000
    7. Amplitude = 0.25!
    8. ' let's not hurt our ears
    9. End Sub
    10. Public Property Frequency As Single
    11. Get
    12. Return Frequency
    13. End Get
    14. Set
    15. End Set
    16. End Property
    17. Public Property Amplitude As Single
    18. Get
    19. Return Amplitude
    20. End Get
    21. Set
    22. End Set
    23. End Property
    24. Public Overrides Function Read(ByVal buffer() As Single, ByVal offset As Integer, ByVal sampleCount As Integer) As Integer
    25. Dim sampleRate As Integer = waveFormat.SampleRate
    26. Dim n As Integer = 0
    27. Do While (n < sampleCount)
    28. buffer((n + offset)) = CType((Me.Amplitude * Math.Sin(((2 _
    29. * (Math.PI _
    30. * (Me.sample * Me.Frequency))) _
    31. / sampleRate))), Single)
    32. Me.sample = (Me.sample + 1)
    33. If (Me.sample >= sampleRate) Then
    34. Me.sample = 0
    35. End If
    36. n = (n + 1)
    37. Loop
    38. Return sampleCount
    39. End Function
    40. End Class


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Dim waveOut As NAudio.Wave.IWavePlayer
    2. Dim recorder As WaveRecorder
    3. Private Sub startStopSineWave()
    4. If (waveOut Is Nothing) Then
    5. Dim dersineWaveProvider = New SineWaveProvider32
    6. dersineWaveProvider.SetWaveFormat(16000, 1)
    7. ' 16kHz mono
    8. dersineWaveProvider.Frequency = 1000
    9. dersineWaveProvider.Amplitude = 0.25!
    10. recorder = New WaveRecorder(dersineWaveProvider, "D:\Dokumente\sine.wav")
    11. waveOut = New NAudio.Wave.WaveOut
    12. waveOut.Init(recorder)
    13. waveOut.Play()
    14. Else
    15. waveOut.Stop()
    16. waveOut.Dispose()
    17. waveOut = Nothing
    18. recorder.Dispose()
    19. recorder = Nothing
    20. End If
    21. End Sub
    22. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    23. startStopSineWave()
    24. End Sub




    Es scheint zunächst auch alles zu klappen: Auf Knopfdruck startet er eine "Aufnahme" und erstellt nach Beendigung am angegebenen Speicherort die WAV, die auch die Länge hat, die es haben soll. Wenn man die WAV jedoch abspielt, hört man nichts. Nichtmal ein bisschen. Mein Stereomix ist aktiviert und mit anderen Programmen laufen Aufnahmen des Systemsounds auch problemlos. Daher muss es an meinem Programm liegen. Ich habe auch schon versucht, die WAV mit dem VLC Media Player zu öffnen, und es lässt sich auch öffnen, jedoch gibt es auch hier keinen Sound.

    Ich hoffe ihr könnt mir da helfen!
    MfG

    *Topic verschoben*

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    @TheChosen0ne Verhält sich der C#-Code genau so?
    Oder hast Du den ausschließlich übersetzt und dann gelöscht?
    Falls Du ihn noch hast, poste mal den Code, den Du übersetzt hast.
    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!
    @TheChosen0ne OK.
    Was brauche ich alles, um den Code compilefähig und lauffähig zu machen?
    - IWaveProvider
    - WaveFormat
    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!
    @TheChosen0ne Sorry, das Packet lässt sich bei mir nicht installieren. ;(
    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!
    Alles klar, ich habe es nun doch geschafft, das Ganze ziemlich einfach mithilfe von NAudio zu lösen.
    Die oben genannten Übersetzungen sind dabei völlig unnötig, zumindest für meinen Gebrauch. Noch dazu ist das viel zu kompliziert. Ich habe im Internet ein englisches NAudio Tutorial auf YT gefunden (tatsächlich aus Zufall gefunden, da nichtmals "NAudio" in Videotitel/-überschrift genannt worden ist). Das Ganze war auf C#, da aber der Sinn hinter alledem gut erklärt worden ist, konnte ich auch problemlos in VB.NET übersetzen. Habe dabei sogar erste Erfahrungen mit Event-Handling gemacht :whistling:

    Für alle die später noch Probleme damit haben, hier der benötigte Quellcode in VB.NET zur Aufnahme mithilfe der API NAudio:
    Spoiler anzeigen

    Klasse "Recorder":
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Recorder
    2. Dim dieWaveSource As NAudio.Wave.WaveIn
    3. Dim dieWaveFile As NAudio.Wave.WaveFileWriter
    4. Public Sub aufnahmeStarten(pGeraetnummer As Integer, pSpeicherort As String)
    5. dieWaveSource = New NAudio.Wave.WaveIn
    6. dieWaveSource.DeviceNumber = pGeraetnummer
    7. dieWaveSource.WaveFormat = New NAudio.Wave.WaveFormat(44100, 1)
    8. AddHandler dieWaveSource.DataAvailable, AddressOf dieWaveSource_DataAvailable
    9. AddHandler dieWaveSource.RecordingStopped, AddressOf dieWaveSource_RecordingStopped
    10. dieWaveFile = New NAudio.Wave.WaveFileWriter(pSpeicherort, dieWaveSource.WaveFormat)
    11. dieWaveSource.StartRecording()
    12. End Sub
    13. Sub dieWaveSource_DataAvailable(sender As Object, e As NAudio.Wave.WaveInEventArgs)
    14. If IsNothing(dieWaveFile) = False Then
    15. dieWaveFile.Write(e.Buffer, 0, e.BytesRecorded)
    16. dieWaveFile.Flush()
    17. End If
    18. End Sub
    19. Sub dieWaveSource_RecordingStopped(sender As Object, e As NAudio.Wave.StoppedEventArgs)
    20. If IsNothing(dieWaveSource) = False Then
    21. dieWaveSource.Dispose()
    22. dieWaveSource = Nothing
    23. End If
    24. If IsNothing(dieWaveFile) = False Then
    25. dieWaveFile.Dispose()
    26. dieWaveFile = Nothing
    27. End If
    28. End Sub
    29. Public Sub aufnahmeStoppen()
    30. dieWaveSource.StopRecording()
    31. End If
    32. End Sub
    33. End Class


    Letztendlich in der Form dann:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private derRecorder As Recorder = New Recorder
    2. Private Sub ButtonStart_Click(sender As Object, e As EventArgs) Handles ButtonStart.Click
    3. Dim save = New SaveFileDialog
    4. If save.ShowDialog <> System.Windows.Forms.DialogResult.OK Then
    5. Return
    6. End If
    7. save.Filter = "Wave File (*.wav)|*.wav;"
    8. Dim geraetNummer As Integer = ListBox1.SelectedIndex
    9. derRecorder = New Recorder
    10. derRecorder.aufnahmeStarten(geraetNummer, save.FileName)
    11. End Sub
    12. Private Sub ButtonStop_Click(sender As Object, e As EventArgs) Handles ButtonStop.Click
    13. derRecorder.aufnahmeStoppen()
    14. End Sub



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