利用C#将PCM格式的Wav进行对文件裁剪截取、淡入淡出、保存为音频文件相关详细代码解释

/// <summary>
 
     /// 文件裁剪截取
 
     /// </summary>
 健康知识平台重庆保胆取石 重庆胆结石医院
     public class WavScissorHelper
 
     {
 
         public static bool GetWavFileScissor(string OriginalAudioFilePath, string DestinedAudioFilePath, int beginCutTime, int endCutTime, ref string errorInfo)
 
         {
 
             if (!File.Exists(OriginalAudioFilePath))
 
             {
 
                 errorInfo = string.Format("源文件:[{0}]不存在!", OriginalAudioFilePath);
 
                 return false;
 
             }
 
             if (!Directory.Exists(Path.GetDirectoryName(DestinedAudioFilePath)))
 
             {
 
                 errorInfo = string.Format("文件夹:[{0}]不存在!", Path.GetDirectoryName(DestinedAudioFilePath));
 
                 return false;
 
             }
 
             if ((beginCutTime < 0) || (endCutTime < 0)
 
                 || (beginCutTime > endCutTime))
 
             {
 
                 errorInfo = string.Format("截取时间[{0}][{1}]有误!", beginCutTime, endCutTime);
 
                 return false;
 
             }
 
             try
 
             {
 
                 WavFile oldFile = new WavFile(OriginalAudioFilePath);
 
                 if (endCutTime > oldFile.PlayTime)
 
                 {
 
                     errorInfo = string.Format("结束截取时间[{0}]大于音频文件播放时间[{1}]!", endCutTime, oldFile.PlayTime);
 
                     return false;
 
                 }
 
                 int timeSpan = endCutTime - beginCutTime;
 
 
 
                 WavFile newFile = new WavFile(DestinedAudioFilePath);
 
                 newFile.WavFormat = oldFile.WavFormat;
 
 
 
                 byte[] newAudioBytes = new byte[oldFile.WavFormat.ByteRate * timeSpan];
 
                 Array.Copy(oldFile.AudioDataBytes, oldFile.WavFormat.ByteRate * beginCutTime, newAudioBytes, 0, newAudioBytes.Length);
 
 
 
                 newFile.WriteWavFile(newAudioBytes);
 
                 return true;
 
             }
 
             catch (Exception e)
 
             {
 
                 return false;
 
 
 
             }
 
         }
 
 
 
     }
 
 
 
     /// <summary>
 
     /// 淡入淡出处理
 
     /// </summary>
 
     public class WavFadeHelper
 
     {
 
         private WavFile _wavFile;
 
        
 
         public WavFadeHelper(string wavFilePath)
 
         {
 
             _wavFile = new WavFile(wavFilePath);
 
         }
 
 
 
 
 
         public bool FadeAtFirstSec(FadeMode fadeMode, long fadeLength)
 
         {
 
             return FadeAtSec(fadeMode, 0, fadeLength);
 
         }
 
 
 
         public bool FadeAtEndSec(FadeMode fadeMode, long fadeLength)
 
         {
 
             long totalTime = _wavFile.PlayTime;
 
             if (totalTime < fadeLength)
 
                 fadeLength = totalTime;
 
             long startTime = totalTime - fadeLength;
 
 
 
             return FadeAtSec(fadeMode, startTime, startTime + fadeLength);
 
         }
 
 
 
         public bool FadeAtSec(FadeMode fadeMode, long startSec, long endSec)
 
         {
 
             //总播放时间
 
             long totalTime = _wavFile.PlayTime;
 
 
 
             //采样位数       
 
             // 16 bit 纵坐标为采样系数 细化为 2^16= 65535份 16位二进制表示 [ 0000 0000 0000 0000 ]
 
             // 即为2Byte (每单位时间内产生 2Byte 的音频数据)
 
 
 
             int byteNumPerSample = _wavFile.WavFormat.BitsPerSample / 8;
 
 
 
             //采样频率
 
             // 11025Hz 横坐标为采样频率 单位时间为: 1/11025 s          
             //单位时间内产生的的音频数据大小为 2Byte * 11025Hz * 声道数          
 
 
 
 
             //audioData 是按字节处理 16bit采样 每次获取两个字节进行处理
 
 
 
             //开始位置 存储单元索引
 
             long startIndex = startSec * byteNumPerSample * _wavFile.WavFormat.SampleRate;
 
             if (startIndex % byteNumPerSample > 0)
 
                 startIndex -= startIndex % byteNumPerSample;
 
 
 
             //结束位置 存储单元索引
 
             long endIndex = endSec * byteNumPerSample * _wavFile.WavFormat.SampleRate;
 
             if (endIndex > _wavFile.AudioDataBytes.Length - 1)
 
                 endIndex = _wavFile.AudioDataBytes.Length - 1;
 
 
 
             //字节数组 音频数据
 
             byte[] audioDatas = _wavFile.AudioDataBytes;
 
 
 
             //初始衰减率
 
             double rate = 1.0;
 
 
 
             //对每个单位时间内的 样点幅值 进行衰减
 
             //从淡化开始时间到结束时间共有 [ 采样频率 * 时间段(s) * 采样位数/8(Byte) ] 个存储单元
 
             //每次取出 采样位数/8(Byte) 个存储单元进行衰减
 
 
 
             // i 的值为每次衰减处理时的 字节读取位置 (索引)
 
             for (int i = (int)startIndex; i < endIndex; i += byteNumPerSample)
 
             {
 
                 //衰减率的方向与淡入淡出有关
 
                 //衰减率的大小与当前读取处理字节的索引位置有关
 
                 if (fadeMode == FadeMode.FadeOut)
 
                     rate = (double)(endIndex - i) / (endIndex - startIndex);
 
                 else
 
                     rate = (double)(i - startIndex) / (endIndex - startIndex);
 
 
 
                 //单位时间内的字节数为1 即采用8bit采样位数  每次只需要对一个字节进行衰减
 
                 if (byteNumPerSample == 1)
 
                 {
 
                     //获取需要衰减的字节值
 
                     byte audioData = audioDatas[i];
 
 
 
                     //进行衰减线性处理
 
                     byte changedAudioData = (byte)((double)audioData * rate);
 
                     //byte changedAudioData = Convert.ToByte((double)audioData * rate);
 
 
 
                     //对原来的值进行更改
 
                     audioDatas[i] = changedAudioData;
 
                 }
 
                 else if (byteNumPerSample == 2)
 
                 {
 
                     //16bit 量化 每单位时间产生2Byte数据 因此取 2Byte 的数据进行衰减处理
 
                     byte[] audioData = new byte[2];
 
                     Array.Copy(audioDatas, i, audioData, 0, 2);
 
 
 
                     //单个样点幅值
 
                     double sample = 0;
 
 
 
                     //转换为整数进行线性处理
 
                     sample = (double)BitConverter.ToInt16(audioData, 0) * rate;
 
 
 
                     //转换为字节存储
 
                     byte[] buffer = BitConverter.GetBytes(Convert.ToInt16(sample));
 
                     if (!BitConverter.IsLittleEndian)
 
                         Array.Reverse(buffer);
 
 
 
                     Array.Copy(buffer, 0, audioDatas, i, 2);
 
                 }
 
             }
 
             _wavFile.WriteWavFile(audioDatas);
 
 
 
             return true;
 
         }
 
     }
 
 
 
     /// <summary>
 
     /// 淡入淡出模式
 
     /// </summary>
 
     public enum FadeMode
 
     {
 
         FadeIn,
 
         FadeOut
 
     }
 
 
 
     /// <summary>
 
     /// WAV 文件
 
     /// </summary>
 
     public class WavFile
 
     {
 
         private WavFormat _wavFormat;   //文件格式
 
         private long _fileLength;       //文件长度
 
         private string _filePath;       //文件路径
 
         private byte[] _audioData;      //语音数据
 
 
 
         private WavFile() { }
 
         public WavFile(string filePath)
 
         {
 
             _filePath = filePath;
 
         }
 
 
 
         /// <summary>
 
         /// 文件格式
 
         /// </summary>
 
         public WavFormat WavFormat
 
         {
 
             get
 
             {
 
                 if (_wavFormat == null)
 
                     _wavFormat = GetWavFormat();
 
 
 
                 return _wavFormat;
 
             }
 
             set { _wavFormat = value; }
 
         }
 
 
 
         /// <summary>
 
         /// 文件大小
 
         /// </summary>
 
         public long FileLength
 
         {
 
             get
 
             {
 
                 if (_wavFormat == null)
 
                     _wavFormat = GetWavFormat();
 
 
 
                 return _fileLength;
 
             }
 
             set { _fileLength = value; }
 
         }
 
 
 
         /// <summary>
 
         /// 播放时长
 
         /// </summary>
 
         public long PlayTime
 
         {
 
             get
 
             {
 
                 if (_wavFormat == null)
 
                     _wavFormat = GetWavFormat();
 
 
 
                 return _audioData.Length / _wavFormat.ByteRate;
 
             }
 
         }
 
 
 
         /// <summary>
 
         /// 语音数据
 
         /// </summary>
 
         public byte[] AudioDataBytes
 
         {
 
             get
 
             {
 
                 if (_wavFormat == null)
 
                     _wavFormat = GetWavFormat();
 
 
 
                 return _audioData;
 
             }
 
             set { _audioData = value; }
 
         }
 
 
 
         /// <summary>
 
         /// 设置Wav文件格式
 
         /// </summary>
 
         /// <param name="bitsPerSample">采样位数</param>
 
         /// <param name="channels">声道数</param>
 
         /// <param name="sampleRate">采样率</param>
 
         public void SetWavFormat(int bitsPerSample, int channels, int sampleRate)
 
         {
 
             _wavFormat = new WavFormat();
 
             _wavFormat.BitsPerSample = bitsPerSample;
 
             _wavFormat.Channels = channels;
 
             _wavFormat.SampleRate = sampleRate;
 
         }
 
 
 
         /// <summary>
 
         /// 写文件
 
         /// </summary>
 
         /// <param name="audioData">音频数据</param>
 
         public void WriteWavFile(byte[] audioData)
 
         {
 
             WriteWavFile(_wavFormat, audioData, 0, audioData.Length);
 
         }
 
 
 
         /// <summary>
 
         /// 写文件
 
         /// </summary>
 
         /// <param name="wavFormat">文件格式</param>
 
         /// <param name="audioData">音频数据</param>
 
         /// <param name="startIndex">audioData数组开始索引位置</param>
 
         /// <param name="length">写入audioData数组长度</param>
 
         public void WriteWavFile(WavFormat wavFormat, byte[] audioData, int startIndex, int length)
 
         {
 
             FileStream fs = null;
 
             BinaryWriter bw = null;
 
             try
 
             {
 
                 fs = new FileStream(_filePath, FileMode.Create, FileAccess.Write);
 
                 bw = new BinaryWriter(fs);
 
                 fs.Position = 0;
 
                 bw.Write(new char[4] { 'R', 'I', 'F', 'F' });
 
                 //ChunkFileSize
 
                 bw.Write((int)(length + 44 - 8));
 
                 bw.Write(new char[8] { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' });
 
                 bw.Write((int)16);
 
                 bw.Write((short)1);
 
                 bw.Write((short)wavFormat.Channels);
 
                 bw.Write(wavFormat.SampleRate);
 
                 bw.Write((int)(wavFormat.SampleRate * ((wavFormat.BitsPerSample * wavFormat.Channels) / 8)));
 
                 bw.Write((short)((wavFormat.BitsPerSample * wavFormat.Channels) / 8));
 
                 bw.Write((short)wavFormat.BitsPerSample);
 
                 bw.Write(new char[4] { 'd', 'a', 't', 'a' });
 
                 bw.Write(length);
 
                 bw.Write(audioData, startIndex, length);
 
             }
 
             finally
 
             {
 
                 if (bw != null)
 
                     bw.Close();
 
                 if (fs != null)
 
                 {
 
                     fs.Close();
 
                     fs.Dispose();
 
                 }
 
             }
 
         }
 
 
 
         /// <summary>
 
         /// 获取Wav文件格式
 
         /// </summary>
 
         /// <returns></returns>
 
         private WavFormat GetWavFormat()
 
         {
 
             FileStream fs = null;
 
             BinaryReader br = null;
 
             WavFormat wavFormat = new WavFormat();
 
 
 
             try
 
             {
 
                 fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read);
 
                 br = new BinaryReader(fs);
 
 
 
                 _fileLength = fs.Length;
 
 
 
                 fs.Position = 22;
 
                 wavFormat.Channels = br.ReadInt16();
 
                 fs.Position = 24;
 
                 wavFormat.SampleRate = br.ReadInt32();
 
                 fs.Position = 28;
 
                 wavFormat.ByteRate = br.ReadInt32();
 
                 fs.Position = 34;
 
                 wavFormat.BitsPerSample = br.ReadInt16();
 
 
 
                 //The audio data
 
                 fs.Position = 44;
 
                 int dataByteSize = (int)(fs.Length - 44);
 
                 if (_audioData == null)
 
                     _audioData = new byte[dataByteSize];
 
                 fs.Read(_audioData, 0, dataByteSize);
 
 
 
             }
 
             finally
 
             {
 
                 if (br != null)
 
                     br.Close();
 
                 if (fs != null)
 
                 {
 
                     fs.Close();
 
                     fs.Dispose();
 
                 }
 
             }
 
             return wavFormat;
 
         }
 
     }
 
 
 
     /// <summary>
 
     /// WAV 文件格式
 
     /// </summary>
 
     public class WavFormat
 
     {
 
         /// <summary>
 
         /// 采样位数
 
         /// </summary>
 
         public int BitsPerSample;
 
         /// <summary>
 
         /// 声道数
 
         /// </summary>
 
         public int Channels;
 
         /// <summary>
 
         /// 采样率
 
         /// </summary>
 
         public int SampleRate;
 
         /// <summary>
 
         /// 传输速率(播放速率)
 
         /// </summary>
 
         public long ByteRate;
 
     }
原文地址:https://www.cnblogs.com/liushunli/p/4020071.html