服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C# 基于NAudio实现对Wav音频文件剪切(限PCM格式)

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

2022-12-12 11:35QianTLL C#

本文主要介绍了C#基于NAudio工具对Wav音频文件进行剪切,可以将一个音频文件剪切成多个音频文件(限PCM格式),感兴趣的小伙伴可以学习一下

前言

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

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

本文是按时间剪切

实现代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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);
                    }
                }
            }
        }
    }
}

调用:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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音频文件剪切(限PCM格式)的文章就介绍到这了,更多相关C# NAudio Wav音频文件剪切内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/qiantao/archive/2021/11/29/15618359.html

延伸 · 阅读

精彩推荐
  • C#c#中SqlTransaction——事务详解

    c#中SqlTransaction——事务详解

    这篇文章主要介绍了c#中SqlTransaction——事务详解 ,具有一定的参考价值,有兴趣的可以了解一下。...

    停留的风4542021-12-11
  • C#如何在C# 中使用 FFmpeg.NET

    如何在C# 中使用 FFmpeg.NET

    这篇文章主要介绍了如何在C# 中使用 FFmpeg.NET,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...

    hellodev9232022-11-07
  • C#详解使用C#编写SqlHelper类

    详解使用C#编写SqlHelper类

    本篇文章主要介绍了使用C#编写SqlHelper类,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    A-Mortal9512022-01-22
  • C#Unity实现人物旋转和移动效果

    Unity实现人物旋转和移动效果

    这篇文章主要为大家详细介绍了Unity实现人物旋转和移动效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    StupidKen7462022-08-20
  • C#C# IQueryable<T>揭开表达式树的神秘面纱

    C# IQueryable<T>揭开表达式树的神秘面纱

    这篇文章主要介绍了C# IQueryable<T>表达式树,对IQueryable<T>感兴趣的同学,必须要仔细看一下...

    农码一生10602022-11-15
  • C#c# 实现观察者模式

    c# 实现观察者模式

    这篇文章主要介绍了c# 实现观察者模式的步骤,帮助大家更好的理解和使用c#实现设计模式,感兴趣的朋友可以了解下...

    xhubobo3702022-10-26
  • C#C# 9.0 特性全面总结

    C# 9.0 特性全面总结

    这篇文章主要介绍了C# 9.0 特性的相关资料,帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...

    张志敏9672022-11-02
  • C#一个状态机的实现

    一个状态机的实现

    本文主要介绍了C#实现一个状态机的思路与方法,具有很好的参考价值,下面跟着小编一起来看下吧...

    诺贝尔8562021-12-22