请问如何将多个wav文件合成一个wav文件

时间:2023-02-06 06:38:02
我用MS-DOS下的Copy/b file1.wav+file2.wav file3.wav命令和自己编代码(将file1.wav、file2.wav的4H<文件大小>、40H<声音大小>处的long int分别相加并分别写入file3.wav相应位置)拷贝结果都是file3.wav大小等于file1.wav+file2.wav,但是声音却只有file1.wav的声音,请问这到底是怎么回事?我应该怎么解决?

19 个解决方案

#1


我的E-Mail:LXM@juwei.net

#2


1.把File2的头(44)去掉
2.把File2的数据接在File1后面,修改File1数据长度(File1数据长度+File2数据长度)

#3


呵呵。楼上说的对。把头剪了。后面的数据堆上去就ok了。

#4


哥哥们,我不但把它们头给剪了,连尾巴都剪了一截,可是没有用呀,帮忙看看吧!
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Copy_Main.h"
#include <io.h>
#include <fcntl.h>

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 int fp1,fp2,fp3;
 long int file_len,len;
 long int file_len1,len1;
 long int file_len2,len2;
 long int len3,file_len3;
 char byte_buf;
 char byte_buf2;
 char byte_buf3[4];
 String str1,str2,str3;


 str1="e:\\1.wav";
 str2="e:\\2.wav";
 str3="e:\\3.wav";
 fp1=open(str1.c_str(),O_RDONLY|O_BINARY);
 fp2=open(str2.c_str(),O_RDONLY|O_BINARY);
 fp3=open(str3.c_str(),O_CREAT|O_RDWR|O_BINARY);

 lseek(fp1,4,SEEK_SET);
 read(fp1,&len3,sizeof(len3));
 file_len1=len3;
 lseek(fp1,40,SEEK_SET);
 read(fp1,&len3,sizeof(len3));
 len1=len3;

 lseek(fp2,4,SEEK_SET);
 read(fp2,&len3,sizeof(len3));
 file_len2=len3;
 lseek(fp2,40,SEEK_SET);
 read(fp2,&len3,sizeof(len3));
 len2=len3;


 file_len=filelength(fp1);
 len=0;
 while(len<file_len)
 {
  lseek(fp1,len,SEEK_SET);
  read(fp1,&byte_buf,1);
  lseek(fp3,0,SEEK_END);
  write(fp3,&byte_buf,1);
  len++;
 }

 file_len=filelength(fp2);
 len=0;
 while(len<file_len-44)
 {
  lseek(fp2,len+44,SEEK_SET);
  read(fp2,&byte_buf2,1);
  lseek(fp3,0,SEEK_END);
  write(fp3,&byte_buf2,1);
  len++;
 }
 /*
 len3=len1+len2;
 //file_len3=filelength(fp1)+filelength(fp2)-44;
 file_len3=file_len1+file_len2-44;
 lseek(fp3,4,SEEK_SET);
 write(fp3,&file_len3,sizeof(file_len3));
 lseek(fp3,40,SEEK_SET);
 write(fp3,&len3,sizeof(len3));
 */
 close(fp1);
 close(fp2);
 close(fp3);
}
//---------------------------------------------------------------------------

#5


兄弟们,帮帮忙吧,我该怎么做?

#6


有好心的朋友帮我这个忙吗?

#7


你两个WAV的取样频率是一样的吗?

#8


file1文件的尾也要去掉

#9


kataboy(小浩子) 朋友:
  是一样的,都是8k,16bit,单声道

laishishenghust(赤脚狂奔) 朋友:
  file1文件尾去掉也已经实验过,不知道你是不是,去掉后成功了?反正我是没有成功,你知道是什么原因吗?

#10


很简单的,我要组织一下

#11



   你首先要知道音频裸数据的长度, 也就是 buffer 的 size 。
   看下面的结构,一开始有 八个字节是一个结构, 第一个 四字节 是标志,刚好等于 ascii 的 "RIFF" ,第二个四字节是总的文件长度减去8。你可以验证一下。(参照16进制阅读数字的方法)
   跟着是第二个数据结构,占12个字节,如果你是标准的 wave 格式的文件,那么就是紧接着两个标志,第一个四字节的标志是 ascii 的 "WAVE" ,第二个 四字节的标志就是 ascii 的 "fmt "(注意,有一个空格),然后剩下的四字节里面藏的是 WAVEFORMATEX 结构的大小(参照MSDN),应该是18个字节。
   然后,当然就是 18个字节的 WAVEFORMATEX 结构里面的值。详细的就不说了,自己查一下 MSDN。 
   在这 18 个字节后面 (按照旧时候的方法),应该是跟着一个8字节的结构的,然后就是 "裸数据" 的开始地址了,这八字节结构的开始四字节是标志,应该等于 ascii 的 "data",然后紧跟着的四字节就是裸数据的大小了,也就是最重要的部分。
   好了,如此一来,你就可以得到音频裸数据的起始位置(紧紧跟在含"data"标志的数据结构的后面),还有就是音频数据的长度了。应该是所有的问题都很容易解决的。

   不过,还要注意,就是现在的很多 .wav 文件都会外加一个数据结构(12字节),就加在 WAVEFORMATEX 的后面和 含 "data" 的数据结构前面。  这个外加的结构 第一个四字节是标志,等于 ascii 码的 "fact",然后第二个四字节的值在大部分情况下都等于 4, 第三个四字节的值也是等于 音频裸数据的长度。  基本上就是这样了。 
   如果你希望追加另外一个音频数据到第一个 wave 文件上,当然,一开头的结构中的总长度要加上,然后,裸数据的长度也要加为总和,之后就是将第二个 wave 的裸数据追加到第一个 wave 文件的裸数据后面了。

#12


GZ

#13


一个wave文件格式:

 1- 4字节:'RIFF'
 5- 8字节:int
 9-12字节:'WAVE'
 
13-16字节:'fmt '(有个空格)
17-20字节:int (保存了18个字节的WAVEFORMATEX格式的内存)
21-38字节:WAVEFORMATEX 结构的内存

39-42字节:'fact'
43-46字节:int(一般是=4,即下一个Chunk需要跳过4个字节)
47-50字节:(可能是保留)

51-54字节:'data'
55-58字节: int (保存Wave文件中Data的长度)

所以可以定义两个结构体就可以读它了。

typedef struct
{
    int FType;
    int Size;
    int RType;
}TWaveFileHeader; 

typedef strcut
{
    int CType;
    int Size;
}TWaveChunkHeader;

两个Wave文件的音频格式相不相同,看文件中WaveFormatEx的各项值相不相同就行了。然后修改data的后面的size就完了。

#14


哦,晕,白打了,楼上的还详细。。。

#15


DOS 的COPY 命令加上个参数就能完成, 以前经常用来合并电影文件

#16


哥们们先谢谢了,我先试试看。

#17


哥哥们,成功了,太高兴了。
请kataboy(小浩子)、copy_paste(木石三)兄弟再到如下帖子领分
http://expert.csdn.net/Expert/topic/1482/1482357.xml?temp=.6055567

#18


我给大家的分呢?

#19


用专门的合并工具?

#1


我的E-Mail:LXM@juwei.net

#2


1.把File2的头(44)去掉
2.把File2的数据接在File1后面,修改File1数据长度(File1数据长度+File2数据长度)

#3


呵呵。楼上说的对。把头剪了。后面的数据堆上去就ok了。

#4


哥哥们,我不但把它们头给剪了,连尾巴都剪了一截,可是没有用呀,帮忙看看吧!
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Copy_Main.h"
#include <io.h>
#include <fcntl.h>

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
 int fp1,fp2,fp3;
 long int file_len,len;
 long int file_len1,len1;
 long int file_len2,len2;
 long int len3,file_len3;
 char byte_buf;
 char byte_buf2;
 char byte_buf3[4];
 String str1,str2,str3;


 str1="e:\\1.wav";
 str2="e:\\2.wav";
 str3="e:\\3.wav";
 fp1=open(str1.c_str(),O_RDONLY|O_BINARY);
 fp2=open(str2.c_str(),O_RDONLY|O_BINARY);
 fp3=open(str3.c_str(),O_CREAT|O_RDWR|O_BINARY);

 lseek(fp1,4,SEEK_SET);
 read(fp1,&len3,sizeof(len3));
 file_len1=len3;
 lseek(fp1,40,SEEK_SET);
 read(fp1,&len3,sizeof(len3));
 len1=len3;

 lseek(fp2,4,SEEK_SET);
 read(fp2,&len3,sizeof(len3));
 file_len2=len3;
 lseek(fp2,40,SEEK_SET);
 read(fp2,&len3,sizeof(len3));
 len2=len3;


 file_len=filelength(fp1);
 len=0;
 while(len<file_len)
 {
  lseek(fp1,len,SEEK_SET);
  read(fp1,&byte_buf,1);
  lseek(fp3,0,SEEK_END);
  write(fp3,&byte_buf,1);
  len++;
 }

 file_len=filelength(fp2);
 len=0;
 while(len<file_len-44)
 {
  lseek(fp2,len+44,SEEK_SET);
  read(fp2,&byte_buf2,1);
  lseek(fp3,0,SEEK_END);
  write(fp3,&byte_buf2,1);
  len++;
 }
 /*
 len3=len1+len2;
 //file_len3=filelength(fp1)+filelength(fp2)-44;
 file_len3=file_len1+file_len2-44;
 lseek(fp3,4,SEEK_SET);
 write(fp3,&file_len3,sizeof(file_len3));
 lseek(fp3,40,SEEK_SET);
 write(fp3,&len3,sizeof(len3));
 */
 close(fp1);
 close(fp2);
 close(fp3);
}
//---------------------------------------------------------------------------

#5


兄弟们,帮帮忙吧,我该怎么做?

#6


有好心的朋友帮我这个忙吗?

#7


你两个WAV的取样频率是一样的吗?

#8


file1文件的尾也要去掉

#9


kataboy(小浩子) 朋友:
  是一样的,都是8k,16bit,单声道

laishishenghust(赤脚狂奔) 朋友:
  file1文件尾去掉也已经实验过,不知道你是不是,去掉后成功了?反正我是没有成功,你知道是什么原因吗?

#10


很简单的,我要组织一下

#11



   你首先要知道音频裸数据的长度, 也就是 buffer 的 size 。
   看下面的结构,一开始有 八个字节是一个结构, 第一个 四字节 是标志,刚好等于 ascii 的 "RIFF" ,第二个四字节是总的文件长度减去8。你可以验证一下。(参照16进制阅读数字的方法)
   跟着是第二个数据结构,占12个字节,如果你是标准的 wave 格式的文件,那么就是紧接着两个标志,第一个四字节的标志是 ascii 的 "WAVE" ,第二个 四字节的标志就是 ascii 的 "fmt "(注意,有一个空格),然后剩下的四字节里面藏的是 WAVEFORMATEX 结构的大小(参照MSDN),应该是18个字节。
   然后,当然就是 18个字节的 WAVEFORMATEX 结构里面的值。详细的就不说了,自己查一下 MSDN。 
   在这 18 个字节后面 (按照旧时候的方法),应该是跟着一个8字节的结构的,然后就是 "裸数据" 的开始地址了,这八字节结构的开始四字节是标志,应该等于 ascii 的 "data",然后紧跟着的四字节就是裸数据的大小了,也就是最重要的部分。
   好了,如此一来,你就可以得到音频裸数据的起始位置(紧紧跟在含"data"标志的数据结构的后面),还有就是音频数据的长度了。应该是所有的问题都很容易解决的。

   不过,还要注意,就是现在的很多 .wav 文件都会外加一个数据结构(12字节),就加在 WAVEFORMATEX 的后面和 含 "data" 的数据结构前面。  这个外加的结构 第一个四字节是标志,等于 ascii 码的 "fact",然后第二个四字节的值在大部分情况下都等于 4, 第三个四字节的值也是等于 音频裸数据的长度。  基本上就是这样了。 
   如果你希望追加另外一个音频数据到第一个 wave 文件上,当然,一开头的结构中的总长度要加上,然后,裸数据的长度也要加为总和,之后就是将第二个 wave 的裸数据追加到第一个 wave 文件的裸数据后面了。

#12


GZ

#13


一个wave文件格式:

 1- 4字节:'RIFF'
 5- 8字节:int
 9-12字节:'WAVE'
 
13-16字节:'fmt '(有个空格)
17-20字节:int (保存了18个字节的WAVEFORMATEX格式的内存)
21-38字节:WAVEFORMATEX 结构的内存

39-42字节:'fact'
43-46字节:int(一般是=4,即下一个Chunk需要跳过4个字节)
47-50字节:(可能是保留)

51-54字节:'data'
55-58字节: int (保存Wave文件中Data的长度)

所以可以定义两个结构体就可以读它了。

typedef struct
{
    int FType;
    int Size;
    int RType;
}TWaveFileHeader; 

typedef strcut
{
    int CType;
    int Size;
}TWaveChunkHeader;

两个Wave文件的音频格式相不相同,看文件中WaveFormatEx的各项值相不相同就行了。然后修改data的后面的size就完了。

#14


哦,晕,白打了,楼上的还详细。。。

#15


DOS 的COPY 命令加上个参数就能完成, 以前经常用来合并电影文件

#16


哥们们先谢谢了,我先试试看。

#17


哥哥们,成功了,太高兴了。
请kataboy(小浩子)、copy_paste(木石三)兄弟再到如下帖子领分
http://expert.csdn.net/Expert/topic/1482/1482357.xml?temp=.6055567

#18


我给大家的分呢?

#19


用专门的合并工具?

#20