问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

C语言编写程序将多个wav文件拼接成一个音频wav文件并播放

发布网友 发布时间:2022-04-23 04:00

我来回答

1个回答

热心网友 时间:2022-04-27 07:08

#include <stdio.h>
#include <string.h>

#define RIFF_SIGN_ID 0x46464952ul
#define WAVE_SIGN_ID 0x45564157ul
#define FMT__SIGN_ID 0x20746D66ul
#define FACT_SIGN_ID 0x74636166ul
#define DATA_SIGN_ID 0x61746164ul

#ifndef DWORD 
typedef unsigned long  DWORD;
#endif

#ifndef WORD 
typedef unsigned short WORD;
#endif

#ifndef BYTE
typedef unsigned char  BYTE;
#endif




struct RIFF_HEADER
{
DWORD RiffID;     // 资源交换文件标志 0x46464952 'R','I','F','F'
DWORD RiffSize;   // 从下个地址开始到文件尾的总字节数
DWORD RiffFormat; // WAV文件标志 0x45564157 'W','A','V','E'
};

struct WAVE_FORMAT
{
WORD  FormatTag;      // 格式种类(值为1时,表示数据为线性PCM编码)
WORD  Channels;       // 通道数,单声道为1,双声道为2
DWORD SamplesPerSec;  // 采样频率
DWORD AvgBytesPerSec; // 每秒所需字节数 
WORD  BlockAlign;     // 数据块对齐单位(每个采样需要的字节数)
WORD  BitsPerSample;  // 每个采样需要的bit数 
WORD  otherInfo;      // 附加信息(可选,通过Size来判断有无)
};

struct FMT_BLOCK
{
DWORD       FmtID;     // 波形格式标志 0x20746D66 'f','m','t',' '
DWORD       FmtSize;   // 波形格式部分长度(一般为00000010H)
WAVE_FORMAT wavFormat; // 波形数据格式
};

struct UNKNOW_BLOCK
{
DWORD ID;   // 未知块
DWORD Size; // 未知块长度
};

struct FACT_BLOCK
{
DWORD FactID;   // 可选部分标识 0x74636166 'f','a','c','t'
DWORD FactSize; // 可选部分长度
BYTE  Data[1];  // 可选部分数据
};

struct DATA_BLOCK
{
DWORD DataID;   // 数据标志符 0x61746164, 'd','a','t','a'
DWORD DataSize; // DATA总数据长度字节
BYTE  Data[1];  // 数据
};


BYTE * openWaveFile(const char *name);
BYTE * getWaveData(BYTE * wav, int * dLen);
void   printWaveFormat(BYTE * wav);
int    saveWaveFile(const char * name, BYTE * wav);
BYTE * catWave(BYTE *& wav1, BYTE *& wav2);
size_t getTotalLen(BYTE * wav);

int main(int argc, char* argv[])
{
int dLen;
BYTE * data1 = openWaveFile("1.wav");
printWaveFormat(data1);
BYTE * data2 = openWaveFile("2.wav");
printWaveFormat(data2);
data1 = catWave(data1, data2);
printWaveFormat(data1);
saveWaveFile("3.wav", data1);
return 0;
}

BYTE * openWaveFile(const char *name)
{
size_t readByte;
FILE * fp = fopen(name, "rb");
if(fp==NULL) return NULL;

RIFF_HEADER fh;
if(fread(&fh, sizeof(fh), 1, fp) != 1)
{
fclose(fp);
printf("Riff Header 文件长度错误\n");
return NULL;
}
if(fh.RiffFormat != WAVE_SIGN_ID || fh.RiffID != RIFF_SIGN_ID)
{
fclose(fp);
printf("文件标识符错误 ID:%08X Format:%08X\n", fh.RiffID, fh.RiffFormat);
return NULL;
}
BYTE * r = new BYTE[fh.RiffSize + 10], *pr;
if(r==NULL)
{
fclose(fp);
printf("内存申请错误\n");
return NULL;
}
readByte = fread(r, 1, fh.RiffSize-4, fp);
if(readByte != fh.RiffSize-4)
{
delete [] r;
printf("wave 文件长度错误 %d %d\n", readByte, fh.RiffSize);
return NULL;
}
fclose(fp);

FMT_BLOCK *fb = (FMT_BLOCK *)r;
if(fb->FmtID != FMT__SIGN_ID)
{
printf("格式标识符错误或格式大小错误ID:%08X\n", fb->FmtID);
delete [] r;
return NULL;
}
if(fb->wavFormat.FormatTag != 1)
{
delete [] r;
printf("不支持的格式 Format:%d\n", fb->wavFormat.FormatTag);
return NULL;
}

pr = r + 8 + fb->FmtSize;
while(1)
{
UNKNOW_BLOCK * ub = (UNKNOW_BLOCK *)pr;
if(ub->ID == FACT_SIGN_ID)
{
printf("Fact 标签 length: %d\n", ub->Size);
pr += 8 + ub->Size ;
}
else break;
}
DATA_BLOCK * db = (DATA_BLOCK *)pr;
if(db->DataID  != DATA_SIGN_ID)
{
delete [] r;
printf("数据错误\n");
return NULL;
}
return r;
}

BYTE * getWaveData(BYTE * wav, int * dLen)
{
UNKNOW_BLOCK * ub = (UNKNOW_BLOCK *)wav;
while(ub->ID != DATA_SIGN_ID)
{
switch(ub->ID)
{
case DATA_SIGN_ID:
break;
case FMT__SIGN_ID:
case FACT_SIGN_ID:
ub = (UNKNOW_BLOCK *)(((BYTE *)ub) + ub->Size + 8);
break;
default:
printf("错误标签 %08X\n", ub->ID );
return NULL;
}
}
DATA_BLOCK * db = (DATA_BLOCK *)ub;
*dLen = db->DataSize;
return db->Data;
}

size_t getTotalLen(BYTE * wav)
{
size_t r = 0;
UNKNOW_BLOCK * ub = (UNKNOW_BLOCK *)wav;
while(1)
{
switch(ub->ID)
{
case DATA_SIGN_ID:
r += ub->Size + 8;
return r;
case FMT__SIGN_ID:
case FACT_SIGN_ID:
r += ub->Size + 8;
ub = (UNKNOW_BLOCK *)(((BYTE *)ub) + ub->Size + 8);
break;
default:
printf("错误标签 %08X\n", ub->ID );
return NULL;
}
}
return -1;
}




void printWaveFormat(BYTE * wav)
{
int len;
getWaveData(wav, &len);
FMT_BLOCK *fb = (FMT_BLOCK *)wav;
printf("Wave 格式:PCM\n");
printf("通道数量:%d\n", fb->wavFormat.Channels );
printf("采样频率:%dHz\n", fb->wavFormat.SamplesPerSec );
printf("每秒所需字节数:%d字节\n", fb->wavFormat.AvgBytesPerSec );
printf("数据块对齐单位:%d字节\n", fb->wavFormat.BlockAlign );
printf("每个采样需要的bit数:%dbit\n", fb->wavFormat.BitsPerSample );
printf("长度:%.2f 秒\n", (double)len / fb->wavFormat.AvgBytesPerSec);
}

BYTE * catWave(BYTE *& wav1, BYTE *& wav2)
{
FMT_BLOCK * fb1 = (FMT_BLOCK *)wav2;
const FMT_BLOCK * fb2 = (const FMT_BLOCK *)wav2;
if(
fb1->wavFormat.AvgBytesPerSec == fb2->wavFormat.AvgBytesPerSec &&
fb1->wavFormat.BitsPerSample  == fb2->wavFormat.BitsPerSample  &&
fb1->wavFormat.BlockAlign     == fb2->wavFormat.BlockAlign     &&
fb1->wavFormat.Channels       == fb2->wavFormat.Channels       &&
fb1->wavFormat.FormatTag      == fb2->wavFormat.FormatTag      &&
fb1->wavFormat.SamplesPerSec  == fb2->wavFormat.SamplesPerSec)
{
int len1 = getTotalLen(wav1), len2;
BYTE * Data2 = getWaveData(wav2, &len2);
BYTE * nD = new BYTE[len1 + len2 + 10];
if(nD == NULL) return NULL;
memcpy(nD, wav1, len1);
delete [] wav1;
wav1 = nD;
BYTE * Data1 = getWaveData(wav1, &len1);
DATA_BLOCK * db1 = (DATA_BLOCK *)(Data1 - 8);
db1->DataSize += len2;
memcpy(Data1 + len1, Data2, len2);
return wav1;
}
return NULL;
}

int saveWaveFile(const char * name, BYTE * wav)
{
FILE *fp = fopen(name, "wb");
if(fp == 0) return 0;
int len = getTotalLen(wav);
RIFF_HEADER rh;
rh.RiffFormat = WAVE_SIGN_ID;
rh.RiffID     = RIFF_SIGN_ID;
rh.RiffSize   = len + 4;
fwrite(&rh, sizeof(rh), 1, fp);
fwrite(wav, 1, len, fp);
fclose(fp);
return 1;
}

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
单机组装6000元预算,INTEL和AMD下不同的配置方案 手上有5000元,想DIY一台台式机,主要是玩大型单机游戏,像孤岛危机2。求... ...及各自优点缺点和如何修改。。 CPU 至强 E3 1230 v2主板 微星Z... 求配家用游戏电脑4000-6000 嘴巴上长水泡怎么办? 嘴巴旁边长了水泡怎么回事 他不回信息的句子 市面上有哪些浪漫又个性的牛仔单品值得入手? 2021年流行什么外套显瘦不挑身材 夏季有哪些百搭又显高级的单品值得选择? 肺部有炎症,用什么消炎药好? 如何用C语言编写程序将多个wav文件拼接成一个音频wav文件并播放 肺部感染吃什么食物 C语言播放.wav格式音频出错 肺部感染可以吃什么 如何用C++打开.wav音频文件并读出数据? 肺部感染吃什么水果好 c语言打开音乐文件? 肺部感染吃什么食物? 请问怎么用纯c编写程序播放wav或者mp3文件? 肺部有炎症吃什么好 肺上有炎症吃什么食物? C语言 播放wav 肺有炎症吃什么水果好 c#播放wav格式音乐 肺部感染吃什么好 C语言声音文件播放 肺部有炎症,咳嗽痰多,吃什么药比较好 C语言播放音频文件的问题.... 肺部炎症的情况下吃什么可以帮助消炎 肺炎吃什么水果蔬菜对肺好 C++ 用playsound播放wav 肺部感染吃什么好,并且一般治疗周期长麽? 一般输什么液 肺部感染吃什么消炎药好 c语言播放wav程序运行不了 养肺应该吃什么最好? 肺部炎症吃什么药? 肺部上呼吸道感染吃什么消炎药? 什么日子是好日了? 日日是好日是什么意思 12月那些好日? 你的春夏秋冬好日在正远派送是什么意思 蒙古语的好日哇是什么意思 好日和是什么意思 好日子为什么叫“黄道吉日”? 今天是好日吗?可以拜神吗? 求结婚登记和结婚仪式的好日 扫舍好日 羊真的会很好日吗 找好日子