混音算法研究

转载请注明原创地址:  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;
}


你可能感兴趣的:(混音算法研究)