首页 新闻 会员 周边 捐助

如何给mp3文件添加wav头文件

0
悬赏园豆:60 [已解决问题] 解决于 2010-09-15 13:46

      已经问了一个多星期了,实在不想问这个转换问题了,原以为就快解决了,但又遇到了问题。o(︶︿︶)o 唉,纠结。微软的ppt可以读取MP3文件,但是当插入mp3文件的时候不能将mp3文件作为一个对象插入到ppt中,插入的只是一个路径,而wav文件却可以,因为它只允许wav文件这样做,但是,如果将MP3文件用代码直接转换成wav文件,文件将是原来mp3的数倍大小,而且转换速度也不容乐观;我找资料了解到了ppt读取wav文件的特点,只读取它的头部(这是我在一个牛人的博客里面看到的),所以我想将每个mp3文件加一个wav文件头。

  各位大虾,我现在已经知道了如何读取mp3文件,知道如何操作mp3文件了,但是现在面临一个问题了,如何给mp3文件添加文件头,我看了一下wav文件的文件头格式,有42个字节,有的可能还有44个字节,格式是这样的
RIFF10018WAVEfmt16111102518data9981,数字代表一些值,字母是wav文件的一些标志,当我将这一行代码插入到每个MP3文件的时候,把mp3文件在此插入到ppt中,仍旧是个地址,没有插入整个MP3对象,请问这是什么原因。谢谢。

由于此问题困扰太久,急需解决,所以多给点分了,呵呵

 

 

下面是我的代码:

private FileStream fs;

//MP3文件路径
string filename = "F:\\1.mp3";

//42个字节的wav文件头部

byte[] wavhead = new byte[42] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite);

     wavhead = System.Text.Encoding.GetEncoding("GBK").GetBytes("RIFF10018WAVEfmt16111102518data9981");
                fs.Seek(0, SeekOrigin.Begin);
                fs.Write(wavhead, 0, wavhead.Length);
                fs.Read(head, 0, head.Length);
                fs.Seek(-128, SeekOrigin.End);
                fs.Read(tail, 0, 128);

问题补充: 如果有用C#做过这方面实现的,麻烦给我提供一下源码,感激不尽!
第一印象的主页 第一印象 | 初学一级 | 园豆:79
提问于:2010-08-23 15:02
< >
分享
最佳答案
0

我再次更新代码,查阅了WAV文件的格式,下面的代码中,有些参数的取值,你需要自己斟酌,我使用了

Windows 7的开机音乐的部分参数值.

 

 

Encoding gbkEncoding = Encoding.GetEncoding("GBK");
byte[] mp3Head = new byte[10] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] mp3Tail = new byte[128];

using (FileStream mp3Stream = File.OpenRead("E:\\cer\\我和春天有个约会.mp3"))
{
mp3Stream.Read(mp3Head,
0, mp3Head.Length);
mp3Stream.Seek(
-128, SeekOrigin.End);
mp3Stream.Read(mp3Tail,
0, 128);

using (FileStream wavStream = File.Open("E:\\cer\\我和春天有个约会.wav", FileMode.Create))
{
int startIndex; // MP3 文件开始读取音频数据的位置。
int dataLen; // 音频数据的长度。

if (gbkEncoding.GetString(mp3Head, 0, 3).ToUpper() == "ID3")
{
startIndex
= (mp3Head[6] & 0x7F) * 0x200000 + (mp3Head[7] & 0x7F) * 0x400 + (mp3Head[8] & 0x7F) * 0x80 + (mp3Head[9] & 0x7F);
dataLen
= (int)mp3Stream.Length - startIndex;
}
else if (gbkEncoding.GetString(mp3Tail, 0, 3).ToUpper() == "TAG")
{
startIndex
= 0;
dataLen
= (int)mp3Stream.Length - 128;
}
else
{
// 非法的 MP3 文件格式。
return;
}

// 开始写 WAV 文件。
using (BinaryWriter bw = new BinaryWriter(wavStream))
{
// 下面是写 WAV 文件头。

// 00H 4 char "RIFF"标志
bw.Write(gbkEncoding.GetBytes("RIFF"),0,4);

// 04H 4 long int 文件长度
bw.Write(44 + dataLen);

// 08H 4 char "WAV"标志
bw.Write(gbkEncoding.GetBytes("WAVE"),0,4);

// 0CH 4 char "fmt"标志 ,注意这里 fmt 后要加一个空格,因此需要 4 个字符。
bw.Write(gbkEncoding.GetBytes("fmt "),0,4);

// 10H 4 过渡字节(不定)
bw.Write(new byte[]{0x16,0x00,0x00,0x00},0,4);

// 14H 2 int 格式类别(10H为PCM形式的声音数据)
bw.Write((Int16)1);

// 16H 2 int 单声道为1,双声道为2通道数
bw.Write((Int16)2);

// 18H 4 long 采样率(每秒样本数),表示每个通道的播放速度
bw.Write((Int32)44100);

// 1CH 4 long 波形音频数据传送速率,其值为通道数×每秒数据
// 位数×每样本的数据位数/8。播放软件利用此值可以估计缓冲区的大小
bw.Write((Int32)176400);

// 20H 2 int 数据块的调整数(按字节算的),其值为通道数×每样本的数据位
// 值/8。播放软件需要一次处理多个该值大小的字节数据,以便将其
// 值用于缓冲区的调整。
bw.Write((Int16)4);

// 22H 2 每样本的数据位数,表示每个声道中各个样本的数据位数。
// 如果有多 个声道,对每个声道而言,样本大小都一样。 24H 4 char
// 数据标记符"data" 28H 4 long int 语音数据的长度
bw.Write((Int16)16);

// 24H 4 char 数据标记符"data"
bw.Write(gbkEncoding.GetBytes("data"),0,4);

// 28H 4 long int 语音数据的长度
bw.Write((Int32)dataLen);

// 下面是写音频数据。
mp3Stream.Seek(startIndex, SeekOrigin.Begin);
byte[] buffer = new byte[4096];
while (true)
{
if (dataLen >= 4096)
{
int count = mp3Stream.Read(buffer, 0, 4096);
bw.Write(buffer,
0, count);
dataLen
-= count;
}
else
{
int count = mp3Stream.Read(buffer, 0, 4096);
bw.Write(buffer,
0, count);
break;
}
}
}
}
}
收获园豆:60
Launcher | 高人七级 |园豆:45050 | 2010-08-23 15:16
文件头填了这个“RIFF10018WAVEfmt16111102518data9981”后,后面是数据,还是mp3的文件头?
Launcher | 园豆:45050 (高人七级) | 2010-08-23 21:54
Mp3分为ID3V1和ID3V2,ID3V2只有头文件没有尾文件,ID3V1只有尾文件没有头文件,他的头文件就在尾部,文件头填写玩上面那一行之后就是数据了。我想把头尾文件都去掉。
第一印象 | 园豆:79 (初学一级) | 2010-08-25 08:14
@第一印象:我修改了下,按照你的方法,你看下能行吗?
Launcher | 园豆:45050 (高人七级) | 2010-08-25 10:49
谢谢,我放进去试了一下,好像没有copyto()方法
第一印象 | 园豆:79 (初学一级) | 2010-08-25 11:24
@第一印象:http://msdn.microsoft.com/zh-cn/library/system.io.filestream.copyto.aspx .net framework 4.0的. 你把CopyTo 改成下边这样: byte[] buf = new byte[4096]; int count = 0; while ((count = mp3Stream.Read(buf, 0, 4096)) > 0) { wavStream.Write(buf, 0, count); }
Launcher | 园豆:45050 (高人七级) | 2010-08-25 12:11
文件能播放,但是仍旧只是一个路径,没有将mp3文件作为一个对象插入进ppt,这说明我们的伪装wav头,没有欺骗到ppt,可能是伪装没弄好,因为我查看了一下真正的wav文件的伪装头在二进制情况下是这样的“RIFF""'..WAVEfmt .........+...+......data?..”,但是我们用“RIFF10018WAVEfmt16111102518data9981”插入进去之后,打开文件的二进制码,仍然是“RIFF10018WAVEfmt16111102518data9981”,所以说,伪装出了问题, 没伪装好。o(︶︿︶)o
第一印象 | 园豆:79 (初学一级) | 2010-08-25 14:19
这什么时候才是个头啊
第一印象 | 园豆:79 (初学一级) | 2010-08-25 14:27
@第一印象:那我还是自己看下WAV的文件头吧.
Launcher | 园豆:45050 (高人七级) | 2010-08-25 14:43
@第一印象:我又更新代码了,这回写WAV文件对了,但是能否在PPT中成功,我就不知道了.
Launcher | 园豆:45050 (高人七级) | 2010-08-25 16:38
谢谢了
第一印象 | 园豆:79 (初学一级) | 2010-08-25 16:42
我先试试
第一印象 | 园豆:79 (初学一级) | 2010-08-25 16:43
还是不行,看来这个问题只能告一段落了,不要急,等我弄出来了,跟大家一起分享分享
第一印象 | 园豆:79 (初学一级) | 2010-08-31 15:54
@第一印象:等你的好消息.
Launcher | 园豆:45050 (高人七级) | 2010-08-31 15:56
其他回答(1)
0

真是替你纠结呀....

Astar | 园豆:40805 (高人七级) | 2010-08-23 15:11
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册