此项目需求是针对.wav格式音频进行操作,转换成相应的.mp3格式的音频文件,对音频进行切割,最后以需求的形式输出,此篇会回顾运用到的一些知识点。
1.MDI子窗口的建立:
首先一个窗体能够创建多个MDI窗体,应当将IsMDIContainer属性设为true;以下为效果图:

控制窗体切换的是一个DotNetBar.TabStrip控件,style属性为Office2007Document,TabLayOutType:FixedWithNavigationBox
创建窗体的代码如下:
01
class="color1">/// <summary>
02
/// 创建MDI子窗体类
03
/// </summary>
04
classCreateMDIWindow
05
{
06
/// <summary>
07
/// 当前程序的主窗体对象
08
/// </summary>
09
public staticForm MainForm { get; set; }
10
11
/// <summary>
12
/// 创建子窗口
13
/// </summary>
14
///
15
<typeparam name="T"> 窗口类型
16
</typeparam>
17
public static void CreateChildWindow
18
<t> () where T : Form, new()
19
// where 子句还可以包括构造函数约束。 可以使用 new 运算符创建类型参数的实例;但类型参数为此必须受构造函数约束
20
// new() 的约束。 new() 约束可以让编译器知道:提供的任何类型参数都必须具有可访问的无参数(或默认)构造函数。
21
{
22
T form = null;
23
24
var childForms = MainForm.MdiChildren;
25
//遍历窗体
26
foreach (Form f inchildForms)
27
{
28
if (f isT)
29
{
30
form = f asT;
31
break;
32
}
33
}
34
//如果没有,则创建
35
if(form == null)
36
{
37
//新建窗体
38
form = newT();
39
//设定窗体的图标
40
form.Icon = System.Drawing.Icon.FromHandle(Properties.Resources.MainIcon.GetHicon());
41
//设定窗体的主图标
42
form.MdiParent = MainForm;
43
//设定窗体的边框类型
44
form.FormBorderStyle = FormBorderStyle.FixedToolWindow;
45
}
46
//窗口如何显示
47
form.WindowState = FormWindowState.Maximized;
48
form.Show();
49
}
50
}
51
</t>
前台点击按钮调用代码:CreateMDIWindow.CreateChildWindow (); <>里为窗体的名称。
2.序列化与反序列化:
当一个系统你有默认的工作目录,默认的文件保存路径,且这些数据时唯一的,你希望每次打开软件都会显示这些数据,也可以更新这些数据,可以使用序列化与反序列化。

我们以项目存储根目录和选择项目为例:
代码如下:
01
[Serializable]
02
public classUserSetting
03
{
04
/// <summary>
05
/// 序列化存储路径
06
/// </summary>
07
private string FilePath{ get { returnPath.Combine(Environment.CurrentDirectory, "User.data"); } }
08
09
/// <summary>
10
/// 音频资源存储目录
11
/// </summary>
12
public stringAudioResourceFolder { get; set; }
13
14
/// <summary>
15
/// 项目名称
16
/// </summary>
17
public stringSolution { get; set; }
18
19
/// <summary>
20
/// 构造函数,创建序列化存储文件
21
/// </summary>
22
publicUserSetting()
23
{
24
if(!File.Exists(FilePath))
25
{
26
FileStream fs = File.Create(FilePath);
27
fs.Close();//不关闭文件流,首次创建该文件后不能被使用买现成会被占用
28
}
29
}
30
31
/// <summary>
32
/// 通过反序列化方法,获得保存的数据
33
/// </summary>
34
publicUserSetting ReadUserSetting()
35
{
36
using (FileStream fs = newFileStream(FilePath, FileMode.Open,FileAccess.Read))
37
{
38
objectob = null;
39
if(fs.Length > 0)
40
{
41
SoapFormatter sf = newSoapFormatter();
42
ob = sf.Deserialize(fs);
43
}
44
return ob asUserSetting;
45
}
46
}
47
48
/// <summary>
49
/// 通过序列化方式,保存数据
50
/// </summary>
51
public void SaveUserSetting(objectobj)
52
{
53
using (FileStream fs = newFileStream(FilePath, FileMode.OpenOrCreate, FileAccess.Write))
54
{
55
SoapFormatter sf = newSoapFormatter();
56
sf.Serialize(fs,obj);
57
}
58
}
59
60
}
3.Datagridview动态生成:

根据设置的楼层生成相应楼层带button按钮的datagridview,并且每层按钮为每层选定选择音乐,代码如下:
01
/// <summary>
02
/// 绑定楼层音乐属性
03
/// </summary>
04
private void BindData(int elevatorLow,intnumber)
05
{
06
try
07
{
08
DataTable list = newDataTable();
09
list.Columns.Clear();
10
list.Columns.Add(newDataColumn("name", typeof(string)));
11
list.Columns.Add(newDataColumn("musicPath", typeof(string)));
12
for (inti =0; i < number; i++)
13
{
14
//不包括楼层0层
15
if(elevatorLow != 0)
16
{
17
list.Rows.Add(list.NewRow());
18
list.Rows[i][0] = elevatorLow;
19
}
20
else{ i--; }
21
elevatorLow++;
22
}
23
dataGridViewX1.DataSource = list;
24
}
25
catch(Exception ex)
26
{ MessageBox.Show(ex.ToString()); }
27
}
选择音乐按钮事件:
01
private void dataGridViewX1_CellContentClick(objectsender, DataGridViewCellEventArgs e)
02
{
03
try
04
{
05
//点击选择按钮触发的事件
06
if(e.RowIndex >= 0)
07
{
08
DataGridViewColumn column = dataGridViewX1.Columns[e.ColumnIndex];
09
if (column isDataGridViewButtonColumn)
10
{
11
OpenFileDialog openMusic = newOpenFileDialog();
12
openMusic.AddExtension = true;
13
openMusic.Multiselect = true;
14
openMusic.Filter = "MP3文件(*.mp3)|*mp3";
15
if(openMusic.ShowDialog() == DialogResult.OK)
16
{
17
dataGridViewX1.Rows[e.RowIndex].Cells[2].Value = Path.GetFileName(openMusic.FileName);
18
}
19
}
20
}
21
}
22
catch(Exception ex)
23
{ MessageBox.Show(ex.ToString()); }
24
}
4.获得音乐文件属性:
使用Shellclass获得文件属性可以参考 点击打开链接

代码如下:
01
/// <summary>
02
/// 获得音乐长度
03
/// </summary>
04
/// <param name="filePath">文件的完整路径
05
public static string[] GetMP3Time(stringfilePath)
06
{
07
stringdirName = Path.GetDirectoryName(filePath);
08
stringSongName = Path.GetFileName(filePath);//获得歌曲名称
09
ShellClass sh = newShellClass();
10
Folder dir = sh.NameSpace(dirName);
11
FolderItem item = dir.ParseName(SongName);
12
stringSongTime = dir.GetDetailsOf(item, 27);//27为获得歌曲持续时间 ,28为获得音乐速率,1为获得音乐文件大小
13
string[] time = Regex.Split(SongTime, ":");
14
returntime;
15
}
5.音频操作:
音频的操作用的fmpeg.exe ,下载地址
fmpeg放在bin目录下,代码如下:
01
/// <summary>
02
/// 转换函数
03
/// </summary>
04
/// <param name="exe">ffmpeg程序
05
/// <param name="arg">执行参数
06
public static void ExcuteProcess(string exe, stringarg)
07
{
08
using (var p = newProcess())
09
{
10
p.StartInfo.FileName = exe;
11
p.StartInfo.Arguments = arg;
12
p.StartInfo.UseShellExecute = false; //输出信息重定向
13
p.StartInfo.CreateNoWindow = true;
14
p.StartInfo.RedirectStandardError = true;
15
p.StartInfo.RedirectStandardOutput = true;
16
p.Start(); //启动线程
17
p.BeginOutputReadLine();
18
p.BeginErrorReadLine();
19
p.WaitForExit();//等待进程结束
20
}
21
}
音频转换的代码如下:
01
private void btnConvert_Click(objectsender, EventArgs e)
02
{
03
//转换MP3
04
if(txtMp3Music.Text != "")
05
{
06
string fromMusic = Statics.Setting.AudioResourceFolder + "\\"+ Statics.Setting.Solution+"\\" + cobFolders.Text + "\\" + txtMusic.Text;//转换音乐路径
07
string toMusic = Statics.Setting.AudioResourceFolder + "\\"+ Statics.Setting.Solution+"\\" + cobFolders.Text + "\\"+ txtMp3Music.Text;//转换后音乐路径
08
intbitrate = Convert.ToInt32(cobBitRate.Text) * 1000;//恒定码率
09
stringHz = cobHz.Text;//采样频率
10
11
try
12
{
13
MP3Convertion.ExcuteProcess("ffmpeg.exe", "-y -ab " + bitrate + " -ar "+ Hz + " -i \"" + fromMusic + "\" \"" + toMusic + "\"");
14
if(cbRetain.Checked == false)
15
{
16
File.Delete(fromMusic);
17
BindList();
18
}
19
else
20
{
21
foreach (ListViewItem lt inlistMusics.Items)
22
{
23
if(lt.Text == txtMusic.Text)
24
{
25
listMusics.Items.Remove(lt);
26
}
27
}
28
}
29
30
//转换完成
31
MessageBox.Show("转换完成");
32
txtMusic.Text = "";
33
txtMp3Music.Text = "";
34
}
35
catch(Exception ex)
36
{ MessageBox.Show(ex.ToString()); }
37
}
38
else
39
{
40
MessageBox.Show("请选择你要转换的音乐");
41
}
42
}
音频切割的代码如下:
01
private void btnCut_Click(objectsender, EventArgs e)
02
{
03
SaveFileDialog saveMusic = newSaveFileDialog();
04
saveMusic.Title = "选择音乐文件存放的位置";
05
saveMusic.DefaultExt = ".mp3";
06
saveMusic.InitialDirectory = Statics.Setting.AudioResourceFolder +"\\" + Statics.Setting.Solution+"\\" + cobFolders.Text;
07
string fromPath = Statics.Setting.AudioResourceFolder + "\\"+ Statics.Setting.Solution +"\\"+ cobFolders.Text + "\\"+ txtMusic.Text;//要切割音乐的物理路径
08
stringstartTime = string.Format("0:{0}:{1}", txtBeginM.Text, txtBeginS.Text).Trim();//歌曲起始时间
09
intduration = (Convert.ToInt32(this.txtEndM.Text) * 60 + Convert.ToInt32(this.txtEndS.Text)) - (Convert.ToInt32(this.txtBeginM.Text) * 60 + Convert.ToInt32(this.txtBeginS.Text));
10
stringendTime = string.Format("0:{0}:{1}", duration / 60, duration % 60);//endTime是持续的时间,不是歌曲结束的时间
11
if(saveMusic.ShowDialog() == DialogResult.OK)
12
{
13
stringsavePath = saveMusic.FileName;//切割后音乐保存的物理路径
14
try
15
{
16
MP3Convertion.ExcuteProcess("ffmpeg.exe", "-y -i \"" + fromPath + "\" -ss "+ startTime + " -t " + endTime + " -acodec copy \""+ savePath+"\"");//-acodec copy表示歌曲的码率和采样频率均与前者相同
17
MessageBox.Show("已切割完成");
18
}
19
catch(Exception ex)
20
{
21
MessageBox.Show(ex.ToString());
22
}
23
}
24
}
切割音频操作系统的知识点就总结道这了,就是fmpeg的应用。