WPF NAudio录音和播放音频文件-实时绘制音频波形图_wpf 音频频谱图-程序员宅基地

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:control="clr-namespace:AudioDemo.Controls"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d" WindowStartupLocation="CenterScreen"
        Title="MainWindow" Height="800" Width="1800">
    <Grid>
        <TextBlock Text="{Binding CurrentState}" Width="502" HorizontalAlignment="Center" VerticalAlignment="Center" Height="58" Margin="272,303,1018,408" FontWeight="Bold" FontSize="22"/>
        <Button Content="开始录音" Width="100" Click="StartRecord_Click"  x:Name="startRecord" Margin="125,76,1567,593" FontSize="22"/>
        <Button Content="结束录音" Width="100" Click="EndRecord_Click" x:Name="endRecord" Margin="125,201,1567,462" FontSize="22"/>
        <ProgressBar  Value="{Binding RecordTime}" HorizontalAlignment="Center" VerticalAlignment="Center" Width="300" Height="30" Margin="370,201,1122,538"/>
        <!--<Button Content="播放录音" Width="100"  x:Name="analysis" Margin="744,76,948,590"/>-->
        <Button Height="125" Width="144" x:Name="btnBoFang"  Click="AnalysisRecord_Click"  HorizontalAlignment="Left"  VerticalAlignment="Top" Canvas.Left="1673" Canvas.Top="859" Margin="751,70,0,0" >
            <Button.Background>
                <ImageBrush ImageSource="切图/播放01.png"/>
            </Button.Background>

        </Button>       
        <control:PolylineWaveFormControl x:Name="polylineWaveFormControl" BorderBrush="#FFFBF8F8" BorderThickness="1" Margin="272,70,1070,593" />

    </Grid>
</Window>

后台部分源码:
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Threading.Tasks;
using System.Windows;

namespace WpfApp1
{
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window, INotifyPropertyChanged
{
NAudioRecorder recorder;
NAudioReader aggregator;
ObservableCollection recordList;
WaveOut waveOutDevice;
int recordTime;
string currentState;
string outputFolder;
object lockList = new object();
bool boolPlay = false;
string strPlayAddress;

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string name)
    {
        if (PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

    /// <summary>
    /// 录音时长
    /// </summary>
    public int RecordTime
    {
        get { return recordTime; }
        set
        {
            recordTime = value;
            this.OnPropertyChanged("RecordTime");
        }
    }

    /// <summary>
    /// 录音文件列表
    /// </summary>
    //public ObservableCollection<string> RecordList
    //{
    //    get { return recordList; }
    //    set
    //    {
    //        recordList = value;
    //        this.OnPropertyChanged("RecoredList");
    //    }
    //}

    /// <summary>
    /// 界面正在执行任务状态
    /// </summary>
    public string CurrentState
    {
        get { return currentState; }
        set
        {
            currentState = value;
            this.OnPropertyChanged("CurrentState");
        }
    }

    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
            this.Closed += MainWindow_Closed;

        waveOutDevice = new WaveOut();
        //RecordList = new ObservableCollection<string>();
        recorder = new NAudioRecorder();

        outputFolder = System.Windows.Forms.Application.StartupPath+ "\\RecoredList\\";
        Directory.CreateDirectory(outputFolder);

        //analysis.IsEnabled = false;
        btnBoFang.IsEnabled = false;
        endRecord.IsEnabled = false;
    }

    private void Recorder_MicrophoneVoiceReceived(object sender, MaxSampleEventArgs f)
    {
        polylineWaveFormControl.AddValue(f.MaxSample);
    }

    /// <summary>
    /// 退出程序时触发,释放相关资源
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void MainWindow_Closed(object sender, EventArgs e)
    {
        if (waveOutDevice != null)
        {
            waveOutDevice.PlaybackStopped -= WaveOutDevice_PlaybackStopped;
            waveOutDevice.Dispose();
        }
        if (recorder != null)
        {
            recorder.StopRec();
        }
        if (aggregator != null)
        {
            aggregator.Stop();
        }
    }

    /// <summary>
    /// 开始录音
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void StartRecord_Click(object sender, RoutedEventArgs e)
    {
        CurrentState = "开始录音";
        var currentFileName = String.Format("NAudioDemo {0:yyy-MM-dd HH-mm-ss}.wav", DateTime.Now);
        var path = Path.Combine(outputFolder, currentFileName);
        recorder.DataAvailable += Recorder_DataAvailable;
        recorder.MaximumCalculated += Recorder_MicrophoneVoiceReceived;
        recorder.SetFileName(path);
        recorder.StartRec();
        lock (lockList)
        {
           // RecordList.Clear();//清空数组
            //RecordList.Add(path);
            strPlayAddress = path;
        }

        endRecord.IsEnabled = true;
        startRecord.IsEnabled = false;
    }

    /// <summary>
    /// 停止录音
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void EndRecord_Click(object sender, RoutedEventArgs e)
    {
        CurrentState = "结束录音";
        recorder.StopRec();
        //analysis.IsEnabled = true;
        btnBoFang.IsEnabled = true;
        startRecord.IsEnabled = true;
        endRecord.IsEnabled = false;
    }

    /// <summary>
    /// 分析本地音频文件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void AnalysisRecord_Click(object sender, RoutedEventArgs e)
    {
        btnBoFang.IsEnabled = false;
        CurrentState = "正在播放录音";
        var inputStream = new AudioFileReader(strPlayAddress); // recordList[0]);
        aggregator = new NAudioReader(inputStream);
        aggregator.MaximumCalculated += Aggregator_MaximumCalculated;
        aggregator.Start();
        waveOutDevice.Init(aggregator);
        waveOutDevice.Volume = 1;
        waveOutDevice.PlaybackStopped += WaveOutDevice_PlaybackStopped;
        waveOutDevice.Play();
    }

    private void Aggregator_MaximumCalculated(object sender, MaxSampleEventArgs e)
    {
        polylineWaveFormControl.AddValue(e.MaxSample);

    }

    /// <summary>
    /// 进度条管理
    /// </summary>
    /// <param name="value"></param>
    private void Recorder_DataAvailable(int value)
    {
        this.RecordTime = value * 10;
        if (value == 10)//倒计时十秒
        {
            recorder.DataAvailable -= Recorder_DataAvailable;
            recorder.MaximumCalculated -= Recorder_MicrophoneVoiceReceived;
            recorder.StopRec();
            recorder = new NAudioRecorder();

            EndRecord_Click(this, new RoutedEventArgs()); //停止录音
            // StartRecord_Click(this, new RoutedEventArgs()); //重新开始录音
        }
    }
    
    /// <summary>
    /// 音频文件播放结束触发事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void WaveOutDevice_PlaybackStopped(object sender, StoppedEventArgs e)
    {
        waveOutDevice.PlaybackStopped -= WaveOutDevice_PlaybackStopped;
        //RecordList.RemoveAt(0);

        //if(recordList.Count > 0)
        //{
        //    AnalysisRecord_Click(null, null);
        //}
        //else
        //{
            CurrentState = "分析录音完成";
            aggregator.Stop();
        btnBoFang.IsEnabled = true;
        //}
    }
}

}

最终效果图
在这里插入图片描述
源码下载
https://download.csdn.net/download/li_shidong/12241607
添加链接描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/li_shidong/article/details/104797827

智能推荐

idea java 运行参数_idea设置JVM运行参数-程序员宅基地

文章浏览阅读1.8k次。对JVM运行参数进行修改是JVM性能调优的重要手段,下面介绍在应用程序开发过程中JVM参数设置的几种方式。方式一java程序运行时指定 -Dproperty=value该参数通常用于设置系统级全局变量值,如配置文件路径,保证该属性在程序中任何地方都可访问。当然,也可以通过在程序中使用System.setProperty进行设置。注意:1、如果-Dproperty=value的value中包含空格,..._idea run property参数

python群发邮件并将excel附件添加到正文_python发邮件插入表格在正文-程序员宅基地

文章浏览阅读8.7k次。本文几个目的: 1。使用smtp库群发邮件 2。添加邮件的附件 3。将Excel附件添加到正文中"""to_addr表示群发集,使用形如('abc.163.com,add.163.com,[email protected]')html表示要展示在正文中的网页或者表格等。password字段表示邮箱的验证码,在打开smtp协议时记得,并不是邮箱的密码。"""def send_email(to_ad_python发邮件插入表格在正文

如何使用SonarQube Scanner扫描器对代码进行扫描-程序员宅基地

文章浏览阅读3.2k次。2019独角兽企业重金招聘Python工程师标准>>> ..._代码扫描工具对转测前代码进行扫描

SQL常用语法( WITH 语句)-程序员宅基地

文章浏览阅读1.3w次,点赞6次,收藏46次。WITH语句

解决MySQL登录出现错误码10061_2008服务器登陆错误10061-程序员宅基地

文章浏览阅读2.5k次,点赞3次,收藏5次。原因: 没有启动MySQL服务解决方案:以管理员身份打开cmd命令行窗口,使用cd命令将目录切换为你MySQL的bin目录下,输入 net start mysql 启动MySQL服务即可解决此问题!!!电脑中搜索服务找到MySQL服务,启动它!管理员身份命令行窗口打开Windows快捷键: Win + X + A如果找不到MySQL服务,需要安装MySQL服务。解决的方法是用管理员的方式打开mysql安装目录bin。执行mysqld.exe -install,安装后就可以启动服务了!..._2008服务器登陆错误10061

STM32移植工程教程 包括解决Keil 一些常见的错误等等_s32ds 移植 keil startup error-程序员宅基地

文章浏览阅读2.9k次,点赞6次,收藏55次。然后打开Keil 在左边的能看到即说明添加成功 出现如图则说明添加成功编译一下,把多余的头文件删去 有6个错误 我们一般从第一个错误开始看 这里的错误 是TIM定时器的结构体没定义,但其实这些在工程里面的库函数这些都已经包含了这时候,找到stm32f10x_conf.h打开,可以看到stm32f10x_tim.h被注释掉了,这就是导致编译错误的原因,只需要删掉注释 重新编译一下即可 重新编译一下 错误就没有了有时候 会遇到引脚冲突,解决方法一修改文件里面的宏定义 更换为别的引脚解决方法二使用重定义功能_s32ds 移植 keil startup error

随便推点

记一次服务器(centos7)出现奇怪进程,占用CPU奇高的排查过程_centos7排查cpu历史高峰进程-程序员宅基地

文章浏览阅读7.3k次,点赞4次,收藏9次。一、现象:通过top命令查看服务器负载,发现特别高,主要原因是由于一个进程特别占用CPU资源,并且这个进程不是我们所需要的进程。此处忘记截图了二、开始排查,怀疑是被人攻击系统,成为肉机了1、通过lastb命令查看系统登录失败的记录,果然发现大量失败记录,并且不停的在增加,如下图:2、然后赶紧修改了远程登录端口:vi /etc/ssh/sshd_config修改其中的po..._centos7排查cpu历史高峰进程

付费短剧小程序源码 小剧场短剧影视小程序源码 带支付收益等 全开源优化版-程序员宅基地

文章浏览阅读339次。全开源付费短剧小程序源码,支持无限滑动、高性能滑动、预加载、视频预览,支持剧情介绍,集合壁纸另外仿抖音滑动效果,支持会员模式,支持用户单独购买等等多功能。

pack_padded_sequence和pad_packed_sequence&&rnn的输出_pack_padded_sequence后怎么用rnn训练-程序员宅基地

文章浏览阅读322次。在使用rnn训练数据时,常会面临数据长度不一致的情况,这时我们需要将各个序列pad到固定长度,方便batch并行训练;但是填充后虽然长度相同,但是会有很多无效的填充值,会浪费计算资源为了使 RNN 可以高效的读取数据进行训练,就需要在 pad 之后再使用 pack_padded_sequence 对数据进行处理;input:pad后的序列(由大到小排好序)需要注意的是,默认条件下,我们必须把输入数据按照序列长度从大到小排列后才能送入 pack_padded_sequence ,否则会报错。这个函数实际上是_pack_padded_sequence后怎么用rnn训练

系统丢失ucrtbased.dll文件一些软件无法运行问题-程序员宅基地

文章浏览阅读202次。其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个ucrtbased.dll文件(挑选合适的版本文件)把它放入到程序或系统目录中,当我们执行某一个.exe程序时,相应的DLL文件就会被调用,因此将缺失的文件放回到原目录之后就能打开你的软件或游戏了.那么出现ucrtbased.dll丢失要怎么解决?_ucrtbased.dll

Pytorch学习笔记(I)——预训练模型(三):VGG11网络结构-程序员宅基地

文章浏览阅读6.4k次,点赞4次,收藏16次。VGG( (features): Sequential( (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): ReLU(inplace) (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_...

小程序 map组件问题 cover-view问题-程序员宅基地

文章浏览阅读864次。使用小程序的组件map时 在开发者工具上一切顺利 但是在真机预览时 发现地图的层级是最高的 任何标签都覆盖不了它 调整z-index值并没有什么效果原因是微信小程序的map、video、canvas、camera等组件都是原生组件,层级是最高的,并不能像原生开发那样使用z-index来控制层级。从1.4.0基础库中增加了一个组件cover-view,用于在map、video、canvas..._map地图上cover-view组件拖动会上下滑动也没