转载请注明原创地址: http://blog.csdn.net/iflychenyang/article/details/8694147
结合上篇转载的日志做了个research,没达到理想的效果(我在一边调程序,一边听音乐,混合出来的声音差点没把我耳朵炸坏掉),还是把程序贴出来吧,明天晚上继续研究。
// // Mixer.cpp // 语音合成助手(iphone上appstore中可下载这款软件) // // Created by chen yang on 13-3-19. // Copyright 2013 陈阳. All rights reserved. // #include <string.h> #include <stdio.h> #include <math.h> #include <malloc.h> /********以下是wave格式文件的文件头格式说明******/ /*------------------------------------------------ | RIFF WAVE Chunk | | ID = 'RIFF' | | RiffType = 'WAVE' | ------------------------------------------------ | Format Chunk | | ID = 'fmt ' | ------------------------------------------------ | Fact Chunk(optional) | | ID = 'fact' | ------------------------------------------------ | Data Chunk | | ID = 'data' | ------------------------------------------------*/ /**********以上是wave文件格式头格式说明***********/ /*wave 文件一共有四个Chunk组成,其中第三个Chunk可以省略,每个Chunk有标示(ID), 大小(size,就是本Chunk的内容部分长度),内容三部分组成*/ struct TWavehead { /****RIFF WAVE CHUNK*/ unsigned char a[4];//四个字节存放'R','I','F','F' long int b; //整个文件的长度-8;每个Chunk的size字段,都是表示除了本Chunk的ID和SIZE字段外的长度; unsigned char c[4];//四个字节存放'W','A','V','E' /****RIFF WAVE CHUNK*/ /****Format CHUNK*/ unsigned char d[4];//四个字节存放'f','m','t','' long int e; //16后没有附加消息,18后有附加消息;一般为16,其他格式转来的话为18 short int f; //编码方式,一般为0x0001; short int g; //声道数目,1单声道,2双声道; long int h; //采样频率; long int i; //每秒所需字节数; short int j; //每个采样需要多少字节,若声道是双,则两个一起考虑; short int k; //即量化位数 /****Format CHUNK*/ /***Data Chunk**/ unsigned char p[4];//四个字节存放'd','a','t','a' long int q; //语音数据部分长度,不包括文件头的任何部分 };//定义WAVE文件的文件头结构体 typedef struct TWavehead TWavehead; void writeHead(FILE *fp, long int filesize) { if (fp == NULL) { return; } const int CHANNELS = 1; const int RATE = 16000; const int SIZE = 16; struct TWavehead wavehead; wavehead.a[0] = 'R'; wavehead.a[1] = 'I'; wavehead.a[2] = 'F'; wavehead.a[3] = 'F'; wavehead.b = filesize - 8; wavehead.c[0] = 'W'; wavehead.c[1] = 'A'; wavehead.c[2] = 'V'; wavehead.c[3] = 'E'; wavehead.d[0] = 'f'; wavehead.d[1] = 'm'; wavehead.d[2] = 't'; wavehead.d[3] = ' '; wavehead.e = 16; wavehead.f = 1; wavehead.g = CHANNELS; wavehead.h = RATE; wavehead.i = RATE*CHANNELS*SIZE/8; wavehead.j = CHANNELS*SIZE/8; wavehead.k = SIZE; wavehead.p[0] = 'd'; wavehead.p[1] ='a'; wavehead.p[2] ='t'; wavehead.p[3] ='a'; wavehead.q = filesize; fseek(fp, 0, SEEK_SET); fwrite(&wavehead, 1, sizeof(wavehead), fp); } void mixWav(char *backgroundFilePath, char *foregroundFilePath, char *dstFilePath) { FILE *backgroundFile = fopen(backgroundFilePath, "rb"); if(NULL == backgroundFile) { printf("Can Not find backgroundFile\r\n "); return ; } FILE *foregroundFile = fopen(foregroundFilePath, "rb"); if(NULL == foregroundFile) { printf("Can Not find foregroundFilePath\r\n "); return ; } FILE *dstFile = fopen(dstFilePath, "wb"); if(NULL == dstFile) { printf("Can Not find dstFilePath\r\n "); return ; } int waveHeadSize = sizeof(struct TWavehead); // 计算第一个文件除文件头后的大小 fseek(backgroundFile, 0, SEEK_SET); void *backgroundHead = malloc(waveHeadSize); int success = fread(backgroundHead, 1, waveHeadSize, backgroundFile); struct TWavehead *backgroundWaveHead = (struct TWavehead *)backgroundHead; printf("headSize:%d,isSuccess:%d",waveHeadSize,success); // 计算第二个文件除文件头后的大小 //fseek(secondFile, 0, SEEK_SET); void *foregroundHead = malloc(waveHeadSize); success = fread(foregroundHead, 1, waveHeadSize, foregroundFile); struct TWavehead *foregroundWaveHead = (struct TWavehead *)foregroundHead; // 计算目标文件除文件头后的大小 int fileSize = foregroundWaveHead->q; // 写入文件头 writeHead(dstFile,fileSize); fseek(backgroundFile, waveHeadSize, SEEK_SET); fseek(foregroundFile, waveHeadSize, SEEK_SET); char sample1, sample2; int value; while(!feof(foregroundFile)) { if(feof(foregroundFile)) { fseek(backgroundFile, waveHeadSize, SEEK_SET); } // 以下是上篇日志中的算法,效果太差了 sample1 = fgetc(foregroundFile); sample2 = fgetc(backgroundFile); if ((sample1 < 0) && (sample2 < 0)) { //value = sample1 + sample2 - (sample1 * sample2 / (-1 *(pow(2,16-1)-1))); double i = 2, j = 15; value = sample1 + sample2 - (sample1 * sample2 / (-1 *(pow(i,j)-1))); } else { //value = sample1 + sample2 - (sample1 * sample2 / (pow(2,16-1)-1)); double i = 2, j = 15; value = sample1 + sample2 - (sample1 * sample2 / (pow(i,j)-1)); } fputc(value, dstFile); } fclose(backgroundFile); fclose(foregroundFile); fclose(dstFile); } int main(int argc,char *argv[]) { mixWav("d:\\game.wav", "d:\\background.wav", "d:\\temp.wav"); return 0; }