0

我正在研究从 nAudio 中的 WaveIn 函数绘制波形。我在网上找到了一个示例,它完全实现了我正在尝试做的事情,但是它使用了一个外部图形库(Scottplot),并且它是用 C# 编程的(我需要 VB)。我已经成功地将它放在标准图表上,并且基本上翻译了所有代码,虽然它编译了,但我的流是空的。我已经尝试解决这个问题好几个星期了,但没有运气。

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;

    using NAudio.Wave; // installed with nuget
    using NAudio.CoreAudioApi;
    using System.Numerics;


    namespace microphone
    {
        public partial class Form1 : Form
        {

            public WaveIn wi;
            public BufferedWaveProvider bwp;
            //public Int32 envelopeMax;

            private int RATE = 44100; // sample rate of the sound card
            private int BUFFERSIZE = (int) Math.Pow(2,13); // must be a multiple of 2
            //private int BUFFERSIZE = 2048; // must be a multiple of 2

            public Form1()
            {
                InitializeComponent();

                // see what audio devices are available
                int devcount = WaveIn.DeviceCount;
                Console.Out.WriteLine("Device Count: {0}.", devcount);

                // get the WaveIn class started
                WaveIn wi = new WaveIn();
                wi.DeviceNumber = 0;
                wi.WaveFormat = new NAudio.Wave.WaveFormat(RATE, 1);

                // create a wave buffer and start the recording
                wi.DataAvailable += new EventHandler<WaveInEventArgs>(wi_DataAvailable);
                bwp = new BufferedWaveProvider(wi.WaveFormat);
                bwp.BufferLength = BUFFERSIZE * 2;

                bwp.DiscardOnBufferOverflow = true;
                wi.StartRecording();

            }

            // adds data to the audio recording buffer
            void wi_DataAvailable(object sender, WaveInEventArgs e)
            {
                bwp.AddSamples(e.Buffer, 0, e.BytesRecorded);
            }

            public void timer1_Tick(object sender, EventArgs e)
            {
                // read the bytes from the stream
                int frameSize = BUFFERSIZE;
                var frames = new byte[frameSize];
                bwp.Read(frames, 0, frameSize);
                if (frames.Length == 0) return;
                if (frames[frameSize - 2] == 0)
                {
                    label1.Text = "removed";
                    return;
                }
                else {
                    label1.Text = "graphing";
                }


                // convert it to int32 manually (and a double for scottplot)
                int SAMPLE_RESOLUTION = 16;
                int BYTES_PER_POINT = SAMPLE_RESOLUTION / 8;
                Int32[] vals = new Int32[frames.Length/BYTES_PER_POINT];
                double[] Ys = new double[frames.Length / BYTES_PER_POINT];
                double[] Xs = new double[frames.Length / BYTES_PER_POINT];
    //            double[] Ys2 = new double[frames.Length / BYTES_PER_POINT];
    //            double[] Xs2 = new double[frames.Length / BYTES_PER_POINT];
                for (int i=0; i<vals.Length; i++)

                {
                    // bit shift the byte buffer into the right variable format
                    byte hByte = frames[i * 2 + 1];
                    byte lByte = frames[i * 2 + 0];
                    vals[i] = (int)(short)((hByte << 8) | lByte);
                    Xs[i] = i;
                    Ys[i] = vals[i];
    //                Xs2[i] = (double)i/Ys.Length*RATE/1000.0; // units are in kHz
                }


                chart1.ChartAreas[0].AxisX.Maximum = 400;
                chart1.ChartAreas[0].AxisX.Minimum= 0;

                chart1.Series[0].Points.DataBindXY(Xs, Ys);

                //update scottplot (FFT, frequency domain)

                /* Ys2 = FFT(Ys);

                chart2.ChartAreas[0].AxisX.Maximum = 10;
                chart2.ChartAreas[0].AxisX.Minimum = 0;            chart2.Series[0].Points.DataBindXY(Xs2.Take(Xs2.Length / 2).ToArray(), Ys2.Take(Ys2.Length / 2).ToArray());

                // update the displays
                Application.DoEvents();
                */

            }

            //public double[] FFT(double[] data)
            //{
            //    double[] fft = new double[data.Length]; // this is where we will store the output (fft)
            //    Complex[] fftComplex = new Complex[data.Length]; // the FFT function requires complex format
            //    for (int i = 0; i < data.Length; i++)
            //    {
            //        fftComplex[i] = new Complex(data[i], 0.0); // make it complex format (imaginary = 0)
            //    }
            //    Accord.Math.FourierTransform.FFT(fftComplex, Accord.Math.FourierTransform.Direction.Forward);
            //    for (int i = 0; i < data.Length; i++)
            //    {
            //        fft[i] = fftComplex[i].Magnitude; // back to double
            //        //fft[i] = Math.Log10(fft[i]); // convert to dB
            //    }
            //    return fft;
            //    //todo: this could be much faster by reusing variables
            //}



            public void chart1_Click(object sender, EventArgs e) { }

        }
    }

那是我修改过的原始代码,并且可以成功运行,没有多余的位(注释掉)。

    Imports NAudio
    Imports NAudio.CoreAudioApi

    Public Class Form1

        Public WithEvents wi As New NAudio.Wave.WaveIn() 'Wave 'in Stream Generates 'by Naudio
        Public WaveFormat As New NAudio.Wave.WaveFormat(44100, 1) 'Wave In format
        'AddHandler wi.DataAvailable, AddressOf StreamWavein_DataAvailable
        Public bwp As New NAudio.Wave.BufferedWaveProvider(wi.WaveFormat)

        'Public wi As NAudio.Wave.WaveIn()
        'Public bwp

        Public Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

            'Dim wi As New NAudio.Wave.WaveIn()
            'wi.DeviceNumber = 0
            'Dim waveforamt As New NAudio.Wave.WaveFormat(44100, 1)
            ''wi.DataAvailable += New EventHandler < WaveInEventArgs > (wi_DataAvailable)\
            'AddHandler wi.DataAvailable, AddressOf StreamWavein_DataAvailable
            'Dim bwp As New NAudio.Wave.BufferedWaveProvider(wi.WaveFormat)

            bwp.BufferLength = ((Math.Pow(2, 13)) * 2)
            bwp.DiscardOnBufferOverflow = True
            wi.StartRecording()


            Chart1.ChartAreas(0).AxisX.Maximum = 400
            Chart1.ChartAreas(0).AxisX.Minimum = 0
        End Sub


        Public Sub StreamWavein_DataAvailable(ByVal sender As Object, ByVal e As NAudio.Wave.WaveInEventArgs) Handles wi.DataAvailable
            bwp.AddSamples(e.Buffer, 0, e.BytesRecorded)
        End Sub



        Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
            Dim frameSize As Integer
            frameSize = Math.Pow(2, 13)
            Dim frames(frameSize) As Byte
            bwp.Read(frames, 0, frameSize)
            If frames.Length = 0 Then
                Return
            End If
            If frames(frameSize - 2) = 0 Then
                Label1.Text = "removed"
                Return
            Else
                Label1.Text = "graphing"
            End If

            Dim SAMPLE_RESOLUTION As Integer
            SAMPLE_RESOLUTION = 16
            Dim BYTES_PER_POINT As Integer
            BYTES_PER_POINT = SAMPLE_RESOLUTION / 8
            Dim vals(frames.Length / BYTES_PER_POINT) As Int32
            Dim Ys(frames.Length / BYTES_PER_POINT) As Double
            Dim Xs(frames.Length / BYTES_PER_POINT) As Double

            Dim i As Integer
            For i = 0 To vals.Length Step 1
                Dim hbyte As Byte
                Dim lbyte As Byte
                hbyte = frames(i * 2 + 1)
                lbyte = frames(i * 2 + 0)
                vals(i) = CInt(CShort((hbyte << 8) Or lbyte))
                Xs(i) = i
                Ys(i) = vals(i)
            Next

            Chart1.Series("Series1").Points.DataBindXY(Xs, Ys)

        End Sub
    End Class

我不确定我哪里出错了,但任何帮助将不胜感激。

4

0 回答 0