C# 使用NAudio合并mp3、wav音频文件
1.什么是wav格式
WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范,用于保存Windows平台的音频信息资源。 通常使用三个参数来表示声音,量化位数,取样频率和采样点振幅。量化位数分为8位,16位,24位三种,声道有单声道和立体声之分,单声道振幅数据为n*1矩阵点,立体声为n*2矩阵点,取样频率一般有11025Hz(11kHz) ,22050Hz(22kHz)和44100Hz(44kHz) 三种。
标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几。
2. WAV文件的组成
偏移地址
|
大小
字节
|
数据块
类型
|
内容
|
00H~03H
|
4
|
4字符
|
资源交换文件标志(RIFF)
|
04H~07H
|
4
|
长整数
|
从下个地址开始到文件尾的总字节数
|
08H~0BH
|
4
|
4字符
|
WAV文件标志(WAVE)
|
0CH~0FH
|
4
|
4字符
|
波形格式标志(fmt ),最后一位空格。
|
10H~13H
|
4
|
整数
|
过滤字节(一般为00000010H),若为00000012H则说明数据头携带附加信息(见“附加信息”)。
|
14H~15H
|
2
|
整数
|
格式种类(值为1时,表示数据为线性PCM编码)
|
16H~17H
|
2
|
整数
|
通道数,单声道为1,双声道为2
|
18H~1BH
|
4
|
长整数
|
采样频率
|
1CH~1FH
|
4
|
长整数
|
波形数据传输速率(每秒平均字节数)
|
20H~21H
|
2
|
整数
|
DATA数据块长度,字节。
|
22H~23H
|
2
|
整数
|
PCM位宽
|
随后
2字节
|
2
|
整数
|
附加信息(可选,由上方过滤字节确定)
|
......................以上为对wav格式的基本了解,最近碰到一个需要合并音频文件的需求,奈何对此文件了解过少,最后借助于NAudio
git地址: https://github.com/naudio/NAudio,结合文件流进行处理。
3.话不多说上代码。首先是安装Naudio的包。
3.1.上传音频文件并调用合并方法【伪代码】
public void UploadOrCombineAudioFile() { HttpFileCollection files = HttpContext.Current.Request.Files; if (files == null || files.Count < 1) return; string upfileType = HttpContext.Current.Request.Form["upfileType"];//文件格式类型 /*...省略符...*/ int maxSize = 1024 * 1024 * 100;//单文件上传最大限制 List<string> dirDic = new List<string> { ".mp3", ".mp4", ".pcm", ".wav" };//文件格式限制 string uploadPath = HttpContext.Current.Server.MapPath("~/AudioFile/TempFile/");//临时路径 if (!Directory.Exists(uploadPath)) Directory.CreateDirectory(uploadPath); string fileType = string.Empty; for (var i = 0; i < files.Count; i++) { var postedfile = files[i]; var inputStream = postedfile.InputStream; if (inputStream.Length > 0) { string thisfileName = files[i].FileName; fileType = Path.GetExtension(thisfileName); if (postedfile.InputStream == null || postedfile.InputStream.Length > maxSize || !dirDic.Contains(fileType.ToLower())) return; /*...我是省略符...*/ int ReadLen = 0; string uploadFileName = uploadPath + thisfileName; byte[] bytes = new byte[10240]; using (FileStream stream = new FileStream(uploadFileName, FileMode.OpenOrCreate))//保存文件到指定待合并文件路径下 { while ((ReadLen = inputStream.Read(bytes, 0, bytes.Length)) > 0) { stream.Write(bytes, 0, ReadLen); } } } } List<string> filepaths = new List<string>(Directory.GetFiles(uploadPath));//获取待合并文件路径 //文件合并后路径 string savePath = HttpContext.Current.Server.MapPath("~/AudioFile/ComBineFile/" + DateTime.Now.ToString("yyyyMMdd") + "/"); if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath); /*...我是省略符...*/ byte[] buffer = new byte[10240]; string savefullName = savePath + DateTime.Now.ToString("yyyyMMddHHmmssff") + upfileType; if (upfileType.ToLower().Equals(".mp3")) CombineMp3(filepaths, savefullName);//mp3合并 else if ((upfileType.ToLower().Equals(".wav"))) CombineWav(filepaths, savefullName);//wav合并 /*...我是省略符...*/ return; }
3.2 .mp3格式合并
//命名空间 using System.IO; using NAudio; using NAudio.Wave; /// <summary> /// Mp3格式合并 /// </summary> /// <param name="inputFiles">待合并文件路径</param> /// <param name="outputfullName">输出文件名</param> private void CombineMp3(List<string> inputFiles, string outputfullName) { using (FileStream outputStream = new FileStream(outputfullName, FileMode.OpenOrCreate)) { foreach (string file in inputFiles) { Mp3FileReader reader = new Mp3FileReader(file); if ((outputStream.Position == 0) && (reader.Id3v2Tag != null)) { outputStream.Write(reader.Id3v2Tag.RawData, 0, reader.Id3v2Tag.RawData.Length); } Mp3Frame frame; while ((frame = reader.ReadNextFrame()) != null) { outputStream.Write(frame.RawData, 0, frame.RawData.Length); } } } }
3.3.wav格式合并
/// <summary> /// wav格式合并 /// </summary> /// <param name="inputFiles">待合并文件</param> /// <param name="outputfullName">输出文件名</param> private void CombineWav(List<string> inputFiles, string outputfullName) { WaveStream waveStream = WaveFormatConversionStream.CreatePcmStream(new WaveFileReader(inputFiles[0])); using (WaveFileWriter waveFileWriter = new WaveFileWriter(outputfullName, waveStream.WaveFormat)) { foreach (string file in inputFiles) { waveStream = WaveFormatConversionStream.CreatePcmStream(new WaveFileReader(file)); byte[] bytes = new byte[waveStream.Length]; waveStream.Position = 0; waveStream.Read(bytes, 0, (int)waveStream.Length); waveFileWriter.Write(bytes, 0, bytes.Length); } } }
未完待续....