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; using System.IO; namespace TestAudio { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private IWaveIn waveIn; private WaveFileWriter writer; List<float> sampleAggregator = new List<float>();//用来储存波形数据 private void btnStart_Click(object sender, EventArgs e) { StartRecording(); } /// <summary> /// 开始录音 /// </summary> private void StartRecording() { if (waveIn != null) return; Text = "start recording...."; btnStart.Text = "正在录制...."; btnStart.Enabled = false; waveIn = new WaveIn { WaveFormat = new WaveFormat(8000, 1) };//设置码率 writer = new WaveFileWriter("test.wav", waveIn.WaveFormat); waveIn.DataAvailable += waveIn_DataAvailable; waveIn.RecordingStopped += OnRecordingStopped; waveIn.StartRecording(); } /// <summary> /// 录音中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void waveIn_DataAvailable(object sender, WaveInEventArgs e) { writer.Write(e.Buffer, 0, e.BytesRecorded); byte[] buffer = e.Buffer; int bytesRecorded = e.BytesRecorded; for (int index = 0; index < e.BytesRecorded; index += 2) { short sample = (short)((buffer[index + 1] << 8) | buffer[index + 0]); float sample32 = sample / 32768f; sampleAggregator.Add(sample32); } int secondsRecorded = (int)(writer.Length / writer.WaveFormat.AverageBytesPerSecond);//录音时间获取 if (secondsRecorded >= 3)//只录制6秒 { waveIn.StopRecording(); Text = "complete"; btnStart.Text = "开始录制"; btnStart.Enabled = true; //------------------------------------开始画波形图。 Text = sampleAggregator.Min() + "," + sampleAggregator.Max(); int baseMidHeight = 50; float h = 0; for (int i = 0; i < sampleAggregator.Count; i+=60) {//大概意思意思 60的步长是怕太多了。 h= sampleAggregator[i] * 300; flowLayoutPanel1.Controls.Add(new Label() { BackColor = Color.Pink, Width = 5, Height = (int)h, Margin = new Padding(0, baseMidHeight-(int)h, 0, 0) }); } //----------------------------------------------------- } } /// <summary> /// 停止录音 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnRecordingStopped(object sender, StoppedEventArgs e) { if (waveIn != null) // 关闭录音对象 { waveIn.Dispose(); waveIn = null; } if (writer != null)//关闭文件流 { writer.Close(); writer = null; } if (e.Exception != null) { MessageBox.Show(String.Format("出现问题 " + e.Exception.Message)); } } private void Form1_Load(object sender, EventArgs e) { } } }
WPF 例子:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using NAudio.Wave; using System.Collections.ObjectModel; using System.ComponentModel; namespace TestAudioWPF { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); listView.DataContext = listView.ItemsSource = sampleAggregator; } private IWaveIn waveIn; private WaveFileWriter writer; ObservableCollection<WaveInfo> sampleAggregator = new ObservableCollection<WaveInfo> ();//用来储存波形数据 /// <summary> /// 开始录音 /// </summary> private void StartRecording() { if (waveIn != null) return; Title = "start recording...."; btnStart.Content = "正在录制...."; btnStart.IsEnabled = false; sampleAggregator.Clear(); waveIn = new WaveIn { WaveFormat = new WaveFormat(8000, 1) };//设置码率 writer = new WaveFileWriter("test.wav", waveIn.WaveFormat); waveIn.DataAvailable += waveIn_DataAvailable; waveIn.RecordingStopped += OnRecordingStopped; waveIn.StartRecording(); } /// <summary> /// 录音中 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void waveIn_DataAvailable(object sender, WaveInEventArgs e) { writer.Write(e.Buffer, 0, e.BytesRecorded); byte[] buffer = e.Buffer; int bytesRecorded = e.BytesRecorded; //------------------------------------开始画波形图。 sampleAggregator.Clear();//可以不清除,就会一直保持历史记录
// short s = BitConverter.ToInt16(e.Buffer, 0);//这样采样比较少,反正是int16型的
// int w= Math.Abs(s / 50);
// sampleAggregator.Add(new WaveInfo() { heigth = w });
for (int index = 0; index < e.BytesRecorded; index += 2) { short sample = (short)((buffer[index + 1] << 8) | buffer[index + 0]); float sample32 = sample / 32768f; if (sample32 > 0.03f) { sampleAggregator.Add(new WaveInfo() { heigth = sample32*300f }); } } //--------------------------------------------------------- int secondsRecorded = (int)(writer.Length / writer.WaveFormat.AverageBytesPerSecond);//录音时间获取 if (secondsRecorded >= 552)//只录制552秒 { waveIn.StopRecording(); Title = "complete"; btnStart.Content = "开始录制"; btnStart.IsEnabled = true; } } /// <summary> /// 停止录音 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void OnRecordingStopped(object sender, StoppedEventArgs e) { if (waveIn != null) // 关闭录音对象 { waveIn.Dispose(); waveIn = null; } if (writer != null)//关闭文件流 { writer.Close(); writer = null; } if (e.Exception != null) { MessageBox.Show(String.Format("出现问题 " + e.Exception.Message)); } } private void Form1_Load(object sender, EventArgs e) { } private void btnStart_Click(object sender, RoutedEventArgs e) { StartRecording(); } } public class WaveInfo :INotifyPropertyChanged{ public event PropertyChangedEventHandler PropertyChanged; private float _heigth; public float heigth { get { return _heigth; } set { if (value != _heigth) { _heigth = value; OnPropertyChanged("heigth"); } } } private string text; public string Text { get { return text; } set { text = value; OnPropertyChanged("Text"); } } protected void OnPropertyChanged(string propertyName = "") { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } } <Window x:Class="TestAudioWPF.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Button x:Name="btnStart" Click="btnStart_Click" Content="btnStart" HorizontalAlignment="Left" Margin="145,20,0,0" VerticalAlignment="Top" Width="169" Height="37"/> <ListView BorderThickness="0" Name="listView" DataContext="sampleAggregator" Height="232" VerticalAlignment="Bottom"> <ListView.ItemTemplate> <DataTemplate> <Label Margin="0" Padding="0" Background="Pink" Width="2" Height="{Binding heigth}"></Label> </DataTemplate> </ListView.ItemTemplate> <ListView.ItemsPanel> <ItemsPanelTemplate> <WrapPanel IsItemsHost="True" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" Orientation="Horizontal" /> </ItemsPanelTemplate> </ListView.ItemsPanel> </ListView> <WrapPanel ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Disabled" Orientation="Horizontal" Height="70" VerticalAlignment="Bottom"> <Label Margin="0" Padding="0" Background="Pink" Width="2" Height="22"></Label> <Label Margin="0" Padding="0" Background="Pink" Width="2" Height="33"></Label> <Label Margin="0" Padding="0" Background="Pink" Width="2" Height="44"></Label> </WrapPanel> </Grid> </Window>
参考:
https://channel9.msdn.com/coding4fun/articles/AutotuneNET
https://github.com/markheath/voicerecorder
http://www.codesoso.com/code/Curve_RealTime.aspx