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

 更新时间:2021年11月29日 17:00:54   作者:QianTLL  
本文主要介绍了C#基于NAudio工具对Wav音频文件进行剪切,可以将一个音频文件剪切成多个音频文件(限PCM格式),感兴趣的小伙伴可以学习一下

前言

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#异步编程详解

    C#异步编程详解

    本文主要介绍异步编程中Task、Async和Await的基础知识。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • C#并发编程入门教程之概述

    C#并发编程入门教程之概述

    这篇文章主要给大家介绍了关于C#并发编程之概述的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用c#具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • 关于C#结构体 你需要知道的

    关于C#结构体 你需要知道的

    这篇文章主要介绍了关于C#结构体的相关知识,以及使用方法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下
    2020-06-06
  • 如何利用反射构建元数据查看器

    如何利用反射构建元数据查看器

    本篇文章是对反射构建元数据查看器进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • C#实现HTML转WORD及WORD转PDF的方法

    C#实现HTML转WORD及WORD转PDF的方法

    这篇文章主要介绍了C#实现HTML转WORD及WORD转PDF的方法,涉及C#实现HTML、WORD及PDF等文件格式转换的相关技巧,需要的朋友可以参考下
    2015-09-09
  • DevExpress实现GridView当无数据行时提示消息

    DevExpress实现GridView当无数据行时提示消息

    这篇文章主要介绍了DevExpress实现GridView当无数据行时提示消息,需要的朋友可以参考下
    2014-08-08
  • C#/VB.NET 实现彩色PDF转为灰度PDF

    C#/VB.NET 实现彩色PDF转为灰度PDF

    本文以C#代码为例介绍如何实现将彩色PDF文件转为灰度(黑白)的PDF文件,即将PDF文档里面的彩色图片或者文字等通过调用方法转为文档页面为灰色调、无彩色效果的文档。快来跟随小编一起学习吧
    2021-11-11
  • C#通过子窗体刷新父窗体的实现方法

    C#通过子窗体刷新父窗体的实现方法

    在一些软件,比如,进销存管理系统中添加销售单信息时,每个销售单都可能对应多种商品,而且在向销售单中添加商品时,一般都是在新弹出的窗体中选择商品,这时就涉及通过子窗体刷新父窗体的问题,本文给大家介绍了C#通过子窗体刷新父窗体的实现方法,需要的朋友可以参考下
    2024-04-04
  • C#实现简单的登录界面

    C#实现简单的登录界面

    我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。
    2015-11-11
  • C#心跳机制服务器的示例代码

    C#心跳机制服务器的示例代码

    心跳机制出现在tcp长连接中,客户端和服务器之见定时发送一种特殊的数据包,本文主要介绍了C#心跳机制服务器的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-06-06

最新评论