程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#實現Wav PCM格式文件,截取與淡入淡出處理

C#實現Wav PCM格式文件,截取與淡入淡出處理

編輯:C#入門知識

因工具需要 對 Wav 文件做處理 包含轉格 截取 淡入淡出處理 ,此處將代碼記下 以備後用。
 
  View Code
  1   /// <summary>
  2     /// 文件截取處理
  3     /// </summary>
  4     public class WavScissorHelper
  5     {
  6         public static bool GetWavFileScissor(string OriginalAudioFilePath, string DestinedAudioFilePath, int beginCutTime, int endCutTime, ref string errorInfo)
  7         {
  8             if (!File.Exists(OriginalAudioFilePath))
  9             {
 10                 errorInfo = string.Format("源文件:[{0}]不存在!", OriginalAudioFilePath);
 11                 return false;
 12             }
 13             if (!Directory.Exists(Path.GetDirectoryName(DestinedAudioFilePath)))
 14             {
 15                 errorInfo = string.Format("文件夾:[{0}]不存在!", Path.GetDirectoryName(DestinedAudioFilePath));
 16                 return false;
 17             }
 18             if ((beginCutTime < 0) || (endCutTime < 0)
 19                 || (beginCutTime > endCutTime))
 20             {
 21                 errorInfo = string.Format("截取時間[{0}][{1}]有誤!", beginCutTime, endCutTime);
 22                 return false;
 23             }
 24             try
 25             {
 26                 WavFile oldFile = new WavFile(OriginalAudioFilePath);
 27                 if (endCutTime > oldFile.PlayTime)
 28                 {
 29                     errorInfo = string.Format("結束截取時間[{0}]大於音頻文件播放時間[{1}]!", endCutTime, oldFile.PlayTime);
 30                     return false;
 31                 }
 32                 int timeSpan = endCutTime - beginCutTime;
 33
 34                 WavFile newFile = new WavFile(DestinedAudioFilePath);
 35                 newFile.WavFormat = oldFile.WavFormat;
 36
 37                 byte[] newAudioBytes = new byte[oldFile.WavFormat.ByteRate * timeSpan];
 38                 Array.Copy(oldFile.AudioDataBytes, oldFile.WavFormat.ByteRate * beginCutTime, newAudioBytes, 0, newAudioBytes.Length);
 39
 40                 newFile.WriteWavFile(newAudioBytes);
 41                 return true;
 42             }
 43             catch (Exception e)
 44             {
 45                 return false;
 46
 47             }
 48         }
 49
 50     }
 51
 52     /// <summary>
 53     /// 淡入淡出處理
 54     /// </summary>
 55     public class WavFadeHelper
 56     {
 57         private WavFile _wavFile;
 58        
 59         public WavFadeHelper(string wavFilePath)
 60         {
 61             _wavFile = new WavFile(wavFilePath);
 62         }
 63
 64
 65         public bool FadeAtFirstSec(FadeMode fadeMode, long fadeLength)
 66         {
 67             return FadeAtSec(fadeMode, 0, fadeLength);
 68         }
 69
 70         public bool FadeAtEndSec(FadeMode fadeMode, long fadeLength)
 71         {
 72             long totalTime = _wavFile.PlayTime;
 73             if (totalTime < fadeLength)
 74                 fadeLength = totalTime;
 75             long startTime = totalTime - fadeLength;
 76
 77             return FadeAtSec(fadeMode, startTime, startTime + fadeLength);
 78         }
 79
 80         public bool FadeAtSec(FadeMode fadeMode, long startSec, long endSec)
 81         {
 82             //總播放時間
 83             long totalTime = _wavFile.PlayTime;
 84
 85             //采樣位數       
 86             // 16 bit 縱坐標為采樣系數 細化為 2^16= 65535份 16位二進制表示 [ 0000 0000 0000 0000 ]
 87             // 即為2Byte (每單位時間內產生 2Byte 的音頻數據)
 88
 89             int byteNumPerSample = _wavFile.WavFormat.BitsPerSample / 8;
 90
 91             //采樣頻率
 92             // 11025Hz 橫坐標為采樣頻率 單位時間為: 1/11025 s          
 93             //單位時間內產生的的音頻數據大小為 2Byte * 11025Hz * 聲道數          
 94
 95
 96             //audioData 是按字節處理 16bit采樣 每次獲取兩個字節進行處理
 97
 98             //開始位置 存儲單元索引
 99             long startIndex = startSec * byteNumPerSample * _wavFile.WavFormat.SampleRate;
100             if (startIndex % byteNumPerSample > 0)
101                 startIndex -= startIndex % byteNumPerSample;
102
103             //結束位置 存儲單元索引
104             long endIndex = endSec * byteNumPerSample * _wavFile.WavFormat.SampleRate;
105             if (endIndex > _wavFile.AudioDataBytes.Length - 1)
106                 endIndex = _wavFile.AudioDataBytes.Length - 1;
107
108             //字節數組 音頻數據
109             byte[] audioDatas = _wavFile.AudioDataBytes;
110
111             //初始衰減率
112             double rate = 1.0;
113
114             //對每個單位時間內的 樣點幅值 進行衰減
115             //從淡化開始時間到結束時間共有 [ 采樣頻率 * 時間段(s) * 采樣位數/8(Byte) ] 個存儲單元
116             //每次取出 采樣位數/8(Byte) 個存儲單元進行衰減
117
118             // i 的值為每次衰減處理時的 字節讀取位置 (索引)
119             for (int i = (int)startIndex; i < endIndex; i += byteNumPerSample)
120             {
121                 //衰減率的方向與淡入淡出有關
122                 //衰減率的大小與當前讀取處理字節的索引位置有關
123                 if (fadeMode == FadeMode.FadeOut)
124                     rate = (double)(endIndex - i) / (endIndex - startIndex);
125                 else
126                     rate = (double)(i - startIndex) / (endIndex - startIndex);
127
128                 //單位時間內的字節數為1 即采用8bit采樣位數  每次只需要對一個字節進行衰減
129                 if (byteNumPerSample == 1)
130                 {
131                     //獲取需要衰減的字節值
132                     byte audioData = audioDatas[i];
133
134                     //進行衰減線性處理
135                     byte changedAudioData = (byte)((double)audioData * rate);
136                     //byte changedAudioData = Convert.ToByte((double)audioData * rate);
137
138                     //對原來的值進行更改
139                     audioDatas[i] = changedAudioData;
140                 }
141                 else if (byteNumPerSample == 2)
142                 {
143                     //16bit 量化 每單位時間產生2Byte數據 因此取 2Byte 的數據進行衰減處理
144                     byte[] audioData = new byte[2];
145                     Array.Copy(audioDatas, i, audioData, 0, 2);
146
147                     //單個樣點幅值
148                     double sample = 0;
149
150                     //轉換為整數進行線性處理
151                     sample = (double)BitConverter.ToInt16(audioData, 0) * rate;
152
153                     //轉換為字節存儲
154                     byte[] buffer = BitConverter.GetBytes(Convert.ToInt16(sample));
155                     if (!BitConverter.IsLittleEndian)
156                         Array.Reverse(buffer);
157
158                     Array.Copy(buffer, 0, audioDatas, i, 2);
159                 }
160             }
161             _wavFile.WriteWavFile(audioDatas);
162
163             return true;
164         }
165     }
166
167     /// <summary>
168     /// 淡入淡出模式
169     /// </summary>
170     public enum FadeMode
171     {
172         FadeIn,
173         FadeOut
174     }
175
176     /// <summary>
177     /// WAV 文件
178     /// </summary>
179     public class WavFile
180     {
181         private WavFormat _wavFormat;   //文件格式
182         private long _fileLength;       //文件長度
183         private string _filePath;       //文件路徑
184         private byte[] _audioData;      //語音數據
185
186         private WavFile() { }
187         public WavFile(string filePath)
188         {
189             _filePath = filePath;
190         }
191
192         /// <summary>
193         /// 文件格式
194         /// </summary>
195         public WavFormat WavFormat
196         {
197             get
198             {
199                 if (_wavFormat == null)
200                     _wavFormat = GetWavFormat();
201
202                 return _wavFormat;
203             }
204             set { _wavFormat = value; }
205         }
206
207         /// <summary>
208         /// 文件大小
209         /// </summary>
210         public long FileLength
211         {
212             get
213             {
214                 if (_wavFormat == null)
215                     _wavFormat = GetWavFormat();
216
217                 return _fileLength;
218             }
219             set { _fileLength = value; }
220         }
221
222         /// <summary>
223         /// 播放時長 www.2cto.com
224         /// </summary>
225         public long PlayTime
226         {
227             get
228             {
229                 if (_wavFormat == null)
230                     _wavFormat = GetWavFormat();
231
232                 return _audioData.Length / _wavFormat.ByteRate;
233             }
234         }
235
236         /// <summary>
237         /// 語音數據
238         /// </summary>
239         public byte[] AudioDataBytes
240         {
241             get
242             {
243                 if (_wavFormat == null)
244                     _wavFormat = GetWavFormat();
245
246                 return _audioData;
247             }
248             set { _audioData = value; }
249         }
250
251         /// <summary>
252         /// 設置Wav文件格式
253         /// </summary>
254         /// <param name="bitsPerSample">采樣位數</param>
255         /// <param name="channels">聲道數</param>
256         /// <param name="sampleRate">采樣率</param>
257         public void SetWavFormat(int bitsPerSample, int channels, int sampleRate)
258         {
259             _wavFormat = new WavFormat();
260             _wavFormat.BitsPerSample = bitsPerSample;
261             _wavFormat.Channels = channels;
262             _wavFormat.SampleRate = sampleRate;
263         }
264
265         /// <summary>
266         /// 寫文件
267         /// </summary>
268         /// <param name="audioData">音頻數據</param>
269         public void WriteWavFile(byte[] audioData)
270         {
271             WriteWavFile(_wavFormat, audioData, 0, audioData.Length);
272         }
273
274         /// <summary>
275         /// 寫文件
276         /// </summary>
277         /// <param name="wavFormat">文件格式</param>
278         /// <param name="audioData">音頻數據</param>
279         /// <param name="startIndex">audioData數組開始索引位置</param>
280         /// <param name="length">寫入audioData數組長度</param>
281         public void WriteWavFile(WavFormat wavFormat, byte[] audioData, int startIndex, int length)
282         {
283             FileStream fs = null;
284             BinaryWriter bw = null;
285             try
286             {
287                 fs = new FileStream(_filePath, FileMode.Create, FileAccess.Write);
288                 bw = new BinaryWriter(fs);
289                 fs.Position = 0;
290                 bw.Write(new char[4] { 'R', 'I', 'F', 'F' });
291                 //ChunkFileSize
292                 bw.Write((int)(length + 44 - 8));
293                 bw.Write(new char[8] { 'W', 'A', 'V', 'E', 'f', 'm', 't', ' ' });
294                 bw.Write((int)16);
295                 bw.Write((short)1);
296                 bw.Write((short)wavFormat.Channels);
297                 bw.Write(wavFormat.SampleRate);
298                 bw.Write((int)(wavFormat.SampleRate * ((wavFormat.BitsPerSample * wavFormat.Channels) / 8)));
299                 bw.Write((short)((wavFormat.BitsPerSample * wavFormat.Channels) / 8));
300                 bw.Write((short)wavFormat.BitsPerSample);
301                 bw.Write(new char[4] { 'd', 'a', 't', 'a' });
302                 bw.Write(length);
303                 bw.Write(audioData, startIndex, length);
304             }
305             finally
306             {
307                 if (bw != null)
308                     bw.Close();
309                 if (fs != null)
310                 {
311                     fs.Close();
312                     fs.Dispose();
313                 }
314             }
315         }
316
317         /// <summary>
318         /// 獲取Wav文件格式
319         /// </summary>
320         /// <returns></returns>
321         private WavFormat GetWavFormat()
322         {
323             FileStream fs = null;
324             BinaryReader br = null;
325             WavFormat wavFormat = new WavFormat();
326
327             try
328             {
329                 fs = new FileStream(_filePath, FileMode.Open, FileAccess.Read);
330                 br = new BinaryReader(fs);
331
332                 _fileLength = fs.Length;
333
334                 fs.Position = 22;
335                 wavFormat.Channels = br.ReadInt16();
336                 fs.Position = 24;
337                 wavFormat.SampleRate = br.ReadInt32();
338                 fs.Position = 28;
339                 wavFormat.ByteRate = br.ReadInt32();
340                 fs.Position = 34;
341                 wavFormat.BitsPerSample = br.ReadInt16();
342
343                 //The audio data
344                 fs.Position = 44;
345                 int dataByteSize = (int)(fs.Length - 44);
346                 if (_audioData == null)
347                     _audioData = new byte[dataByteSize];
348                 fs.Read(_audioData, 0, dataByteSize);
349
350             }
351             finally
352             {
353                 if (br != null)
354                     br.Close();
355                 if (fs != null)
356                 {
357                     fs.Close();
358                     fs.Dispose();
359                 }
360             }
361             return wavFormat;
362         }
363     }
364
365     /// <summary>
366     /// WAV 文件格式
367     /// </summary>
368     public class WavFormat
369     {
370         /// <summary>
371         /// 采樣位數
372         /// </summary>
373         public int BitsPerSample;
374         /// <summary>
375         /// 聲道數
376         /// </summary>
377         public int Channels;
378         /// <summary>
379         /// 采樣率
380         /// </summary>
381         public int SampleRate;
382         /// <summary>
383         /// 傳輸速率(播放速率)
384         /// </summary>
385         public long ByteRate;
386     }


 摘自 MyNewID
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved