0
$\begingroup$

I've written a VB.NET WinForms application that allows me to perform a Fourier Transform to find the amplitudes of discrete frequencies to represent that “strength” as a bar graph. The code for this is already ready and tested.

Now I only need the “wave” from the sound card – I must tap this wave somehow. How does it work? I know this is digital, but can I get the analog wave? The speakers are getting an analog signal, too.

There should be a way to "see" the wave, right? Is there anything I can download from Visual Studio's own NuGet Package Manager for this? (I only know the use of NAudio to get the volume of an Device Audio End Point).

I've already used the search function a little here at SO, but found very little…

I don't want to play a song by using the VLC Player and then pick that song with my programme to show the bar graph while playing the song with a player. I need to get the analog output frequency band of the sound card.

I hope this is not a much too broad a question to be answered here.

$\endgroup$
8
  • $\begingroup$ Your best bet is to look for a VB.Net library to interact with the sound card. By the way, everything on the software side of the sound card is discrete-time. $\endgroup$
    – MBaz
    Commented Dec 17, 2021 at 18:11
  • $\begingroup$ ok, thank you, @MBaz. I already asked the question over at Stackoverflow, unfortunately no one could suggest a library there. $\endgroup$
    – Christian
    Commented Dec 17, 2021 at 18:15
  • $\begingroup$ This is the first result when I search for vb.net "sound card": stackoverflow.com/questions/55406315/… It looks like this is fairly doable? $\endgroup$
    – MBaz
    Commented Dec 17, 2021 at 18:39
  • $\begingroup$ That's about picking a device from a collection of devices / list the names; done by oneself (instead NAudio) $\endgroup$
    – Christian
    Commented Dec 17, 2021 at 18:42
  • $\begingroup$ Yeah, but if you can pick a device, you should also be able to read from it, right? $\endgroup$
    – MBaz
    Commented Dec 17, 2021 at 18:59

1 Answer 1

0
$\begingroup$

I can answer my question today for future readers. I watched a YouTube video and found that you can get a new byte array every few milliseconds using NAudio and a few variables.

You always add 2 bytes together and write this result into a newly declared double array. This is then used to run the Fourier transformation.

Given my circumstances and settings (sample rate of my sound card, size of the buffer, ...) there is a double array of 4097 doubles as length and a requested time of 43 milliseconds.

''' <summary>
    ''' sample rate of the soundcard in Hertz
    ''' </summary>
    Private ReadOnly Samplerate As Integer = 192000
    Private ReadOnly BufferSize As Integer = CInt(Math.Pow(2, 13)) ' 8192
    Private bwp As NAudio.Wave.BufferedWaveProvider = Nothing
    ''' <summary>
    ''' 43
    ''' </summary>
    Private usedMilliseconds As Double
    Private cnt As Integer = 0
    ''' <summary>
    ''' to hold the latest soundcard data which we will graph. <para></para>
    ''' Größe dieses Arrays wird BufferSize ÷ 2 +1, also 4097.
    ''' </summary>
    Private DataArray As Double()

    
    Private Sub AudioDataAvailable(ByVal sender As Object, e As NAudio.Wave.WaveInEventArgs)
        bwp.AddSamples(e.Buffer, 0, e.BytesRecorded)
    End Sub

    Private Sub Start_Listening()
        Dim wi As New NAudio.Wave.WaveIn()
        wi.DeviceNumber = 1
        wi.WaveFormat = New NAudio.Wave.WaveFormat(Samplerate, 1)
        wi.BufferMilliseconds = CInt((CDbl(BufferSize) / CDbl(Samplerate) * 1000.0))
        usedMilliseconds = wi.BufferMilliseconds
        AddHandler wi.DataAvailable, AddressOf AudioDataAvailable
        bwp = New NAudio.Wave.BufferedWaveProvider(wi.WaveFormat)
        bwp.BufferLength = BufferSize * 2
        bwp.DiscardOnBufferOverflow = True

        Try
            wi.StartRecording()
        Catch ex As NAudio.MmException
            MessageBox.Show($"Could not record from audio device!{NewLine}{NewLine}{ex.Message}",
                            "",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error)
        End Try
    End Sub

    Public Sub getLatestData()
        Dim audioBytes As Byte() = New Byte(BufferSize - 1) {}
        bwp.Read(audioBytes, 0, BufferSize)
        If audioBytes.Length = 0 Then Return
        If audioBytes(BufferSize - 2) = 0 Then Return
        Dim BYTES_PER_POINT As Integer = 2
        Dim graphPointCount As Integer = audioBytes.Length \ BYTES_PER_POINT

        DataArray = New Double(graphPointCount) {}

        For i As Integer = 0 To graphPointCount - 1
            DataArray(i) = CDbl(BitConverter.ToInt16(audioBytes, i * 2))
        Next
    End Sub

So thanks again to @MBaz! :)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.