• C# NAudio录音和播放音频文件-实时绘制音频波形图(从音频流数据获取,而非设备获取)


      NAudio的录音和播放录音都有对应的类,我在使用Wav格式进行录音和播放录音时使用的类时WaveIn和WaveOut,这两个类是对功能的回调和一些事件触发。

      在WaveIn和WaveOut之外还有对音频流读写使用的WaveFileWriter和WaveFileReader类,具体细节可查看其源码进行分析。

      其中绘制音频波形图根据录制和播放需要不同途径实现。

      1.录音时实时显示波形图,在录音时实时获取需要使用WaveIn.DataAvailable回调事件,在这个回调事件中会传递出音频流数据,数据类型Byte[],这就是音频内容

      但这个Byte数组需要还原为真实的数据,它的真实数据类型需根据PCM写入时的数据格式定,主要有8bit、16bit、24bit、32bit,如写入时是16bit就需将其转换为16bit数据

      然后根据WaveIn.WaveFormat的channels去获取音频波形值,然后输出出来,具体示例如下:

     private void waveSource_DataAvailable(object sender, WaveInEventArgs e)
            {
                if (waveFile != null)
                {
                    waveFile.Write(e.Buffer, 0, e.BytesRecorded);
                    waveFile.Flush();
    
                   
                    float[] sts = new float[e.Buffer.Length / channels];
                    int outIndex = 0;
                    for (int n = 0; n < e.Buffer.Length; n += channels)
                    {
                        sts[outIndex++] = BitConverter.ToInt16(e.Buffer, n) / 32768f;
                    }
    
                    for (int n = 0; n < sts.Length; n += channels)
                    {
                        Add(sts[n]);
                    }
                }
            }

      其中Add()方法就是添加波形值到UI控件上的方法,可根据自己需求实现。 

     2.播放录音文件时显示波形图

      播放录音时需初始化AudioFileReader类,并传入需要播放的文件路径,并将这个类传入WaveOut类中,最后用继承自ISampleProvider的类加载和初始化调用Play方法,然后会调用到WaveOut类Read方法时,会可以使用AudioFileReader.Read()方法进行获取参数,获取的是float数组,可直接用于绘制波形图

       private void AnalysisRecord_Click(object sender, RoutedEventArgs e)
            {
               
                var inputStream = new AudioFileReader(recordList[0]);
                ISampleProvider aggregator = new NAudioReader(inputStream);
                aggregator.MaximumCalculated += Aggregator_MaximumCalculated;
                aggregator.Start();
                waveOutDevice.Init(aggregator);
                waveOutDevice.Volume = 0;
                waveOutDevice.PlaybackStopped += WaveOutDevice_PlaybackStopped;
                waveOutDevice.Play();
            }
    public int Read(float[] buffer, int offset, int count)///这个函数是ISampleProvider调用的函数 
    { var samplesRead = source.Read(buffer, offset, count); for (int n = 0; n < samplesRead; n += channels) { Add(buffer[n + offset]); } return samplesRead; }

      至于绘制波形的WPF细节就在Demo中看吧,主要要注意WaveIn和WaveOut、WaveFileReader和WaveFileWriter相关内容,具体可下源码和Demo看下

      具体可调试示例如下:示例 (也是粗浅学习,可交流,轻拍砖)

      写的比较乱,可跳转到下一篇,写的相对具体点

  • 相关阅读:
    CentOs上安装Oracle 10g
    多线程更新form
    C#中写INI文件的方法
    C语言的函数大全,参数列表,数字的81016进制转换
    CCS 3.3 操作C函数读写文件
    关于XML文档读写
    关于MathType的一些用法
    DateTime Proc
    拖拽获得文件路径
    用事件进行窗口间参数传递
  • 原文地址:https://www.cnblogs.com/Khan-Sadas/p/11434729.html
Copyright © 2020-2023  润新知