<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      ?

      ? ? ?下午寫了一篇關(guān)于NAudio的錄音、播放和波形圖的博客,不太滿意,感覺寫的太亂,又總結(jié)了下

      ? ? ?
      NAudio是個(gè)相對成熟、開源的C#音頻開發(fā)工具,它包含錄音、播放錄音、格式轉(zhuǎn)換、混音調(diào)整等功能。本次介紹主要功能有音頻、錄音文件播放、實(shí)時(shí)音頻流波形圖顯示等。具體如下:

      1. 錄音

      ? ? ? NAudio錄音主要使用WaveIn和WaveFileWriter兩個(gè)類

      ? ?1.1?? WaveIn

      ? ? ?
      WaveIn的功能是對錄音的音頻參數(shù)進(jìn)行設(shè)置以及對數(shù)據(jù)的采集,參數(shù)如通道數(shù)、采樣率、平均數(shù)據(jù)傳輸速率(WaveFormat)、數(shù)據(jù)回調(diào)事件、錄音停止回調(diào)函數(shù)等參數(shù)?

      ? ? ? 其中,DataAvailable為數(shù)據(jù)回調(diào)參數(shù),是在錄音時(shí)實(shí)時(shí)將錄音數(shù)據(jù)傳遞出來,有需要使用錄音數(shù)據(jù)的可以訂閱該事件進(jìn)行接收業(yè)務(wù)和相關(guān)處理。

      ? ?1.2?? WaveFileWriter

      ? ? ?該類是創(chuàng)建相對應(yīng)格式的音頻文件,并提供想對應(yīng)的寫入數(shù)據(jù)方法、保存方法等,具體如下:
      public class WaveFileWriter : Stream { public WaveFileWriter(Stream outStream,
      WaveFormat format);public WaveFileWriter(string filename, WaveFormat format); ~
      WaveFileWriter();public override long Position { get; set; } public override
      bool CanWrite { get; } public override bool CanRead { get; } public WaveFormat
      WaveFormat {get; } public TimeSpan TotalTime { get; } public override long
      Length {get; } public string Filename { get; } public override bool CanSeek {
      get; } public static void CreateWaveFile(string filename, IWaveProvider
      sourceProvider);public static void CreateWaveFile16(string filename,
      ISampleProvider sourceProvider);public static void WriteWavFileToStream(Stream
      outStream, IWaveProvider sourceProvider);public override void Flush(); public
      override int Read(byte[] buffer, int offset, int count); public override long
      Seek(long offset, SeekOrigin origin); public override void SetLength(long
      value);public override void Write(byte[] data, int offset, int count);
      [Obsolete("Use Write instead")] public void WriteData(byte[] data, int offset,
      int count); [Obsolete("Use WriteSamples instead")] public void WriteData(short
      [] samples,int offset, int count); public void WriteSample(float sample); public
      void WriteSamples(short[] samples, int offset, int count); public void
      WriteSamples(float[] samples, int offset, int count); protected override void
      Dispose(bool disposing); protected virtual void UpdateHeader(BinaryWriter
      writer); }
      ? ? ?在調(diào)用上是先調(diào)用WaveIn的DataAvailable回調(diào)函數(shù),讀取其數(shù)據(jù)并寫入流文件,最后保存到本地。

      2. 播放錄音

      播放錄音主要用到AudioFileReader、WaveOut三個(gè)類和接口

      ? ? ? 2.1?? AudioFileReader

      ? ? ? ? ? AudioFileReader主要負(fù)責(zé)讀取音頻文件,驗(yàn)證音頻文件格式,對外部提供讀取數(shù)據(jù)接口,具體如下:
      public class AudioFileReader : WaveStream, ISampleProvider { public
      AudioFileReader(string fileName); public string FileName { get; } public
      override WaveFormat WaveFormat { get; } public override long Length { get; }
      public override long Position { get; set; } public float Volume { get; set; }
      public override int Read(byte[] buffer, int offset, int count); public int Read(
      float[] buffer, int offset, int count); protected override void Dispose(bool
      disposing); }
      ?

      ? ? ?2.2?? WaveOut

      ? ? ? ?
      WaveOut的工作是播放音頻,它調(diào)用AudioFileReader.Read進(jìn)行數(shù)據(jù)讀取,對讀取的數(shù)據(jù)進(jìn)行播放,主要工作流程是從獲取數(shù)據(jù),并將數(shù)據(jù)進(jìn)行播放成音頻
      public class WaveOut : IWavePlayer, IDisposable, IWavePosition { public
      WaveOut();public WaveOut(IntPtr windowHandle); public WaveOut(WaveCallbackInfo
      callbackInfo);~WaveOut(); public static int DeviceCount { get; } public
      PlaybackState PlaybackState {get; } public WaveFormat OutputWaveFormat { get; }
      public int DeviceNumber { get; set; } public int NumberOfBuffers { get; set; }
      public int DesiredLatency { get; set; } public float Volume { get; set; } public
      event EventHandler<StoppedEventArgs> PlaybackStopped; public static
      WaveOutCapabilities GetCapabilities(int devNumber); public void Dispose();
      public long GetPosition(); public void Init(IWaveProvider waveProvider); public
      void Pause(); public void Play(); public void Resume(); public void Stop();
      protected void Dispose(bool disposing); }
      ?

      3. 波形圖繪制

      ? ? ?
      ?錄音時(shí)繪制波形圖需要在DataAviliable回調(diào)函數(shù)中獲取音頻數(shù)據(jù)并將其從byte[]轉(zhuǎn)換為float[],然后用float[]數(shù)據(jù)做為波形圖的輸入即可,這個(gè)過程源碼上寫一個(gè)數(shù)據(jù)包的波形圖數(shù)據(jù)為waveSource.WaveFormat.SampleRate
      / 100,原理上我還沒搞懂,但是的確是這么操作顯示是對的,具體如下:
      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 / 2]; int outIndex = 0;
      for (int n = 0; n < e.Buffer.Length; n += 2) { sts[outIndex++] =
      BitConverter.ToInt16(e.Buffer, n) / 32768f; } for (int n = 0; n < sts.Length; n
      += channels) { Add(sts[n]); } } }
      ?

      ? ?
      需要注意的是WaveFormat的通道數(shù)設(shè)置、PCM的格式設(shè)置,上述代碼都是基于通道數(shù)為2、PCM為16bit的情況下,如這兩項(xiàng)修改會發(fā)生轉(zhuǎn)換和調(diào)用失敗等問題

      ? ? 可調(diào)試Demo:示例Demo <https://download.csdn.net/download/qq_17005083/11644031>

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點(diǎn)信息
      問題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          粉嫩小仙女扒开腿喷水免费 | 色色色9999 | 久久精品观看 | 亚洲高清视频在线观看在线观看 | 网红操逼 | 国产精品操屄视频 | 快穿之尤物h啪肉np苏玛丽 | 久操精品视频 | 久久久久久亚洲视频 | 91久久精品日日躁夜夜躁欧美 |