C#基于NAudio工具对Wav音频文件剪切(限PCM格式)

  • A+
所属分类:.NET技术
摘要

C#基于NAudio工具对Wav音频文件进行剪切,将一个音频文件剪切成多个音频文件

C#基于NAudio工具对Wav音频文件进行剪切,将一个音频文件剪切成多个音频文件

注:调用方法前需要导入NAudio.dll或者在NuGet程序管理器搜索NAudio并安装

本文是按时间剪切,直接撸代码:

using NAudio.Wave; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;  namespace XXX.util {     public static class WavFileUtils     {         /// <summary>         /// 基于NAudio工具对Wav音频文件剪切(限PCM格式)         /// </summary>         /// <param name="inPath">目标文件</param>         /// <param name="outPath">输出文件</param>         /// <param name="cutFromStart">开始时间</param>         /// <param name="cutFromEnd">结束时间</param>         public static void TrimWavFile(string inPath, string outPath, TimeSpan cutFromStart, TimeSpan cutFromEnd)         {             using (WaveFileReader reader = new WaveFileReader(inPath))             {                 int fileLength = (int)reader.Length;using (WaveFileWriter writer = new WaveFileWriter(outPath, reader.WaveFormat))                 {                     float bytesPerMillisecond = reader.WaveFormat.AverageBytesPerSecond / 1000f;                     int startPos = (int)Math.Round(cutFromStart.TotalMilliseconds * bytesPerMillisecond);                     startPos = startPos - startPos % reader.WaveFormat.BlockAlign;                     int endPos = (int)Math.Round(cutFromEnd.TotalMilliseconds * bytesPerMillisecond);                     endPos = endPos - endPos % reader.WaveFormat.BlockAlign;                     //判断结束位置是否越界                     endPos = endPos > fileLength ? fileLength : endPos;                     TrimWavFile(reader, writer, startPos, endPos);                 }             }         }          /// <summary>         /// 重新合并wav文件         /// </summary>         /// <param name="reader">读取流</param>         /// <param name="writer">写入流</param>         /// <param name="startPos">开始流</param>         /// <param name="endPos">结束流</param>         private static void TrimWavFile(WaveFileReader reader, WaveFileWriter writer, int startPos, int endPos)         {             reader.Position = startPos;             byte[] buffer = new byte[1024];             while (reader.Position < endPos)             {                 int bytesRequired = (int)(endPos - reader.Position);                 if (bytesRequired > 0)                 {                     int bytesToRead = Math.Min(bytesRequired, buffer.Length);                     int bytesRead = reader.Read(buffer, 0, bytesToRead);                     if (bytesRead > 0)                     {                         writer.Write(buffer, 0, bytesRead);                     }                 }             }         }     } }

调用:

string filePath = "D:\wav\test.wav";//需要切割的文件路径 int cutTimeSpan = 20;//切割的时间片段时间(秒) FileInfo fi = new FileInfo(filePath); //获取录音文件时长(秒) int fileTime = (int)Util.Cover(Util.GetVoiceTime(filePath)) / 1000; //计算文件需要切割多少等份 decimal fileNum = Math.Ceiling((decimal)fileTime / cutTimeSpan); int i = 0; while (i < fileNum) {     string nowTime = Util.GetTimeStamp();//当前时间戳     //切割后保存的文件绝对地址     var outputPath = System.IO.Path.Combine(fi.Directory.FullName, string.Format("{0}_{1}{2}", fi.Name.Replace(fi.Extension, ""), nowTime, fi.Extension));     //切割的开始时间     TimeSpan cutFromStart = TimeSpan.FromSeconds(i * cutTimeSpan);     //切割的结束时间     TimeSpan cutFromEnd = cutFromStart + TimeSpan.FromSeconds(cutTimeSpan);     //音频切割     WavFileUtils.TrimWavFile(recordFile.FilePath, outputPath, cutFromStart, cutFromEnd);     i++; }

Util 类:

using Shell32; using System; using System.Diagnostics; using System.IO; using System.Net; using System.Net.Sockets; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms;  namespace XXX.util {     class Util     {         /// <summary>         /// 获取时间戳         /// </summary>         /// <returns></returns>         public static string GetTimeStamp()         {             TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);             return Convert.ToInt64(ts.TotalMilliseconds).ToString();         }          /// <summary>         /// 返回音频时长         /// </summary>         /// <param name="SongPath">音频文件路径</param>         /// <returns></returns>         public static string GetVoiceTime(string SongPath)         {             string dirName = Path.GetDirectoryName(SongPath);             string SongName = Path.GetFileName(SongPath);             ShellClass sh = new ShellClass();             Folder dir = sh.NameSpace(dirName);             FolderItem item = dir.ParseName(SongName);             string SongTime = Regex.Match(dir.GetDetailsOf(item, -1), "\d:\d{2}:\d{2}").Value;//返回音频时长             return SongTime;         }        /// <summary>         /// 时间格式转毫秒值         /// </summary>         /// <param name="time">时间字符串</param>         /// <returns></returns>         public static long Cover(string time)         {             string[] a = time.Split(':');             if (long.Parse(a[0]) == 0 && long.Parse(a[1]) == 0)             {                 return long.Parse(a[2]) * 1000;             }             else if (long.Parse(a[0]) == 0 && long.Parse(a[1]) != 0)             {                 return (long.Parse(a[1]) * 60 + long.Parse(a[2])) * 1000;             }             else if (long.Parse(a[0]) != 0 && long.Parse(a[1]) == 0)             {                 return ((long.Parse(a[0]) * 60 * 60) + long.Parse(a[2])) * 1000;             }             else if (long.Parse(a[0]) != 0 && long.Parse(a[1]) != 0)             {                 return (((long.Parse(a[0]) * 60) + long.Parse(a[1])) * 60) * 1000;             }             return 0;         }     } }

 效果图:

C#基于NAudio工具对Wav音频文件剪切(限PCM格式)

参考:

https://github.com/naudio/NAudio

https://stackoverflow.com/questions/42170640/trim-a-wav-file

https://markheath.net/post/trimming-wav-file-using-naudio

总结:实践是检验真理的唯一标准。