C#实现WAV音频单声道提取
2011-03-20 21:29
639 查看
作者:Joseph Pan (转载请注明出处/article/5414907.html )
喜欢买碟或者卡拉ok的朋友一定不会对声道这个术语陌生。通常我们在音像店买回来的VCD或者DVD都是双声道的形式,唱片商在录制唱片时往往提供了两个或多个声道,以保存不同的音频内容,以形成立体声效。左声道保存的大多为一些背景声效,如卡拉OK的消音伴唱。而右声道保存的往往是较为主要的声音,比如主唱的歌声。利用多声道技术,听众可以清晰地分辨出各种乐器来自的方向,从而使音乐更富想象力,更加接近于临场感受。
有时候我们只需要音频里的单声道内容,比如喜欢用电脑录制卡拉ok的朋友就经常为了找歌曲的伴唱而流连于各大伴奏网站。现在的网络翻唱非常流行,很多网络歌手就是先搜索喜欢的歌曲的伴奏,然后利用Adobe Audition(前身就是大名鼎鼎的CoolEdit)录制自己的演唱,然后加一些简单的降噪和压限处理,最后mix到伴奏的音轨里面。尽管利用Audition也可以完成单声道的提取工作,但是操作起来比较复杂。
其实对WAV的单声道提取并不困难。关键在于对WAV文件格式的理解。
一、WAV的文件头
WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范。所有的WAV都有一个文件头,这个文件头包含了音频流的编码参数。
表1 WAV的文件头
由表1我们可以得到以下几个重要的信息:
16H~17H处记录通道数,当值为1时,表示文件为单声道;当值为2时,表示文件为双声道。
18H~1BH处记录采样频率。它的取值与声卡的支持情况有关。常见的有8000、11025、22050、44100、48000、96000等。其中,44100是大多数歌曲文件采用的标准采样频率。
22H~23H处记录样本数据位数。即每一个采样的长度。常见的有8位和16位。这里还包含了另外一个信息:若样本的数据位数为n,对于双声道文件,则低n/2位用于存放左声道;高n/2位用于存放右声道。
根据这三点信息,我们可以自己编程实现单声道的提取。下面我们就来一步步动手实现。由于程序涉及的只是简单的二进制文件读写操作,因此这里只举C#作简单示例,其他语言的处理与之大同小异。
二、文件读取类的编写
为了方便以后对WAV文件的研究,我们可以先单独写一个WAV文件读取类,专门获取文件头的每一块信息:
singleChannelExtract
四、实验结果
根据上面的分析,完成单声道提取器如图1所示。
图1 单声道提取器
运行该程序后,点击“open...”按钮,打开文件打开对话框,选中要进行单声道提取的文件。完成后,Format Info栏将显示该wav文件的信息。之后,单击“Extract!”按钮,弹出一个文件保存对话框,选择要保存的路径点确定,开始提取单声道,完成后将提示“Done!”。
图2和图3分别给出了对一段音频进行右声道提取前和提取后的结果。
图2 提取右声道前
图3 提取右声道后
注意图3中原来的左声道内容已经被右声道的内容覆盖,因此此时虽然还是双声道,但两个声道的内容是一样的,因此在使用上与单声道并没有区别。但如果只想保留一个声道,则可以根据前面的阐述,将每个采样值n/2位内容提取出来并合并成一个文件,再修改头文件相关数据,从而达到需要的结果。
『附相关程序下载』
喜欢买碟或者卡拉ok的朋友一定不会对声道这个术语陌生。通常我们在音像店买回来的VCD或者DVD都是双声道的形式,唱片商在录制唱片时往往提供了两个或多个声道,以保存不同的音频内容,以形成立体声效。左声道保存的大多为一些背景声效,如卡拉OK的消音伴唱。而右声道保存的往往是较为主要的声音,比如主唱的歌声。利用多声道技术,听众可以清晰地分辨出各种乐器来自的方向,从而使音乐更富想象力,更加接近于临场感受。
有时候我们只需要音频里的单声道内容,比如喜欢用电脑录制卡拉ok的朋友就经常为了找歌曲的伴唱而流连于各大伴奏网站。现在的网络翻唱非常流行,很多网络歌手就是先搜索喜欢的歌曲的伴奏,然后利用Adobe Audition(前身就是大名鼎鼎的CoolEdit)录制自己的演唱,然后加一些简单的降噪和压限处理,最后mix到伴奏的音轨里面。尽管利用Audition也可以完成单声道的提取工作,但是操作起来比较复杂。
其实对WAV的单声道提取并不困难。关键在于对WAV文件格式的理解。
一、WAV的文件头
WAV为微软公司(Microsoft)开发的一种声音文件格式,它符合RIFF(Resource Interchange File Format)文件规范。所有的WAV都有一个文件头,这个文件头包含了音频流的编码参数。
偏移地址 | 字节数 | 类型 | 内容 |
00H~03H | 4 | 字符 | 资源交换文件标志(RIFF) |
04H~07H | 4 | 长整数 | 从下个地址开始到文件尾的总字节数 |
08H~0BH | 4 | 字符 | WAV文件标志(WAVE) |
0CH~0FH | 4 | 字符 | 波形格式标志(FMT) |
10H~13H | 4 | 整数 | 过滤字节(一般为00000010H) |
14H~15H | 2 | 整数 | 格式种类(值为1,表示数据PCMμ律编码的数据) |
16H~17H | 2 | 整数 | 通道数,单声道为1,双声道为2 |
18H~1BH | 4 | 长整数 | 采样频率 |
1CH~1FH | 4 | 长整数 | 波形数据传输速率(每秒平均字节数) |
20H~21H | 2 | 整数 | 数据的调整数(按字节计算) |
22H~23H | 2 | 整数 | 样本数据位数 |
由表1我们可以得到以下几个重要的信息:
16H~17H处记录通道数,当值为1时,表示文件为单声道;当值为2时,表示文件为双声道。
18H~1BH处记录采样频率。它的取值与声卡的支持情况有关。常见的有8000、11025、22050、44100、48000、96000等。其中,44100是大多数歌曲文件采用的标准采样频率。
22H~23H处记录样本数据位数。即每一个采样的长度。常见的有8位和16位。这里还包含了另外一个信息:若样本的数据位数为n,对于双声道文件,则低n/2位用于存放左声道;高n/2位用于存放右声道。
根据这三点信息,我们可以自己编程实现单声道的提取。下面我们就来一步步动手实现。由于程序涉及的只是简单的二进制文件读写操作,因此这里只举C#作简单示例,其他语言的处理与之大同小异。
二、文件读取类的编写
为了方便以后对WAV文件的研究,我们可以先单独写一个WAV文件读取类,专门获取文件头的每一块信息:
singleChannelExtract
/// <summary> /// singleChannelExtract /// 用于提取单声道 /// </summary> /// <param name="from">源文件路径</param> /// <param name="to">目的文件路径</param> /// <param name="flag">0:提取左声道;1:提取右声道</param> private void singleChannelExtract(string from, string to, int flag) { //判断是否为双声道 WaveAccess wa = new WaveAccess(from); if (wa.Channel == 2) { //获取位数 ushort bitNum = wa.BitNum; int pos1 = 0, pos2 = 0; int lth = (int)(wa.Data.Length * 2 / bitNum); for (int i = 0; i < wa.Data.Length; i += (int)bitNum) { for (int j=0; j<(int)(bitNum);j++) { for (int k = 0; k < bitNum / 2; k++) { //判断要提取的声道类型 switch(flag) { case 0://提取左声道 wa.Data[(int)(k+bitNum/2)] = wa.Data[k]; break; case 1://提取右声道 wa.Data[k] = wa.Data[(int)(k + bitNum / 2)]; break; default: MessageBox.Show("Sorry. Only left or right channel is supported for now!"); return; } } } } /***写入文件 ***/ wa.bulidWave(to); wa = null; MessageBox.Show("Done!"); return; } else { MessageBox.Show("The song already has single channel!"); return; }
四、实验结果
根据上面的分析,完成单声道提取器如图1所示。
图1 单声道提取器
运行该程序后,点击“open...”按钮,打开文件打开对话框,选中要进行单声道提取的文件。完成后,Format Info栏将显示该wav文件的信息。之后,单击“Extract!”按钮,弹出一个文件保存对话框,选择要保存的路径点确定,开始提取单声道,完成后将提示“Done!”。
图2和图3分别给出了对一段音频进行右声道提取前和提取后的结果。
图2 提取右声道前
图3 提取右声道后
注意图3中原来的左声道内容已经被右声道的内容覆盖,因此此时虽然还是双声道,但两个声道的内容是一样的,因此在使用上与单声道并没有区别。但如果只想保留一个声道,则可以根据前面的阐述,将每个采样值n/2位内容提取出来并合并成一个文件,再修改头文件相关数据,从而达到需要的结果。
『附相关程序下载』
相关文章推荐
- C#实现WAV音频单声道提取
- [置顶] WAV音频MFCC参数提取 + DTW语音识别算法 C++代码实现
- c#简单实现提取网页内容
- visual studio 2010环境下在C#程序中嵌入、播放 wav音频文件 图文介绍
- C# 提取PPT文本和图片的实现方案
- C#.Net实现AutoCAD块属性提取
- javaCV开发详解之7:让音频转换更加简单,实现通用音频编码格式转换、重采样等音频参数的转换功能(以pcm16le编码的wav转mp3为例)
- 提取aspnet_Profile中自定义的用户属性(C#实现)
- TTS5.1语音引擎(中文)实现文本阅读和音频输出为WAV
- C#实现网页正文提取算法
- 用C#实现多种方式播放Wav声音
- 转载:C#如何实现把word文档内的图片提取出来
- C#实现网页正文提取算法ok
- 用ace_dvd_audio_extractor实现DVD音频提取
- 关天WINCE的AC97音频驱动实现左右声道交换的方法概述(转)
- C#调用FFMPEG实现桌面录制(视频+音频+生成本地文件)【笔记】
- visual studio 2010环境下在C#程序中嵌入、播放 wav音频文件 图文介绍
- C#提取PPT文本和图片的实现方法
- [FFMPEG-2]最想实现的第一点一个功能-从mp3中提取pcm数据,重采样和加wav头
- C#中用API实现MP3等音频文件的播放类(转)