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

2022-07-20,,,,

目录
  • 前言
  • 实现代码
  • 效果图

前言

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格式)的文章就介绍到这了,更多相关c# naudio wav音频文件剪切内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

《C# 基于NAudio实现对Wav音频文件剪切(限PCM格式).doc》

下载本文的Word格式文档,以方便收藏与打印。