1. 程式人生 > >程式猿有一天也會成為工程獅!

程式猿有一天也會成為工程獅!

1、線性疊加後求平均

優點:不會產生溢位,噪音較小;

缺點:衰減過大,影響通話質量;

1 2 3 4 5 short  remix(short buffer1,short buffer2) { int value = buffer1 + buffer2; return (short)(value/2); }

2、歸一化混音(自適應加權混音演算法)

思路:使用更多的位數(32 bit)來表示音訊資料的一個樣本,混完音後在想辦法降低其振幅,使其仍舊分佈在16 bit所能表示的範圍之內,這種方法叫做歸一法;

方法:為避免發生溢位,使用一個可變的衰減因子對語音進行衰減。這個衰減因子也就代表語音的權重,衰減因子隨著音訊資料的變化而變化,所以稱為自適應加權混音。當溢位時,衰減因子較小,使得溢位的資料在衰減後能夠處於臨界值以內,而在沒有溢位時,又讓衰減因子慢慢增大,使資料較為平緩的變化。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 void Mix(char sourseFile[10][SIZE_AUDIO_FRAME],int number,char *objectFile) { //歸一化混音 int const MAX=32767; int const MIN=-32768; double f=1; int output; int i = 0,j = 0; for (i=0;i<SIZE_AUDIO_FRAME/2;i++) {
int temp=0; for (j=0;j<number;j++) { temp+=*(short*)(sourseFile[j]+i*2); }                 output=(int)(temp*f); if (output>MAX) { f=(double)MAX/(double)(output); output=MAX; } if (output<MIN) { f=(double)MIN/(double)(output); output=MIN; } if (f<1) { f+=((double)1-f)/(double)32; } *(short*)(objectFile+i*2)=(
short)output;
} }

3、Symbian6.1上實現的混音是個比較麻煩的問題,因為程式只能同時播放一個音樂,實現混音就需要程式自己來實現。下面是我從newlc上找到的一個關於PCM脈衝編碼的音訊訊號的混音實現,其中包含了一個關鍵的混音演算法!

1 2 3 4 if( data1 < 0 && data2 < 0) date_mix = data1+data2 - (data1 * data2 / -(pow(2,16-1)-1)); else date_mix = data1+data2 - (data1 * data2 / (pow(2,16-1)-1));

4、切割時間片,重取樣演算法

可以把各個通道的聲音疊到一起,讓聲音的取樣率按倍增加,如果提高聲音的播放頻率,聲音可以正常的播放,聲音實現了疊加;如果不想修改聲音的播放輸出頻率,可以通過聲音的重取樣後輸出自己想要的輸出頻率;

5、下面是上面的混音的測試程式碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 #include <stdio.h> #include <stdlib.h> #include <math.h> #define IN_FILE1 "1.wav" #define IN_FILE2 "2.wav" #define OUT_FILE "remix.pcm" #define SIZE_AUDIO_FRAME (2) void Mix(char sourseFile[10][SIZE_AUDIO_FRAME],int number,char *objectFile) { //歸一化混音 int const MAX=32767; int const MIN=-32768; double f=1; int output; int i = 0,j = 0; for (i=0;i<SIZE_AUDIO_FRAME/2;i++) { int temp=0; for (j=0;j<number;j++) { temp+=*(short*)(sourseFile[j]+i*2); }                 output=(int)(temp*f); if (output>MAX) { f=(double)MAX/(double)(output); output=MAX; } if (output<MIN) { f=(double)MIN/(double)(output); output=MIN; } if (f<1) { f+=((double)1-f)/(double)32; } *(short*)(objectFile+i*2)=(short)output; } } int main() { FILE * fp1,*fp2,*fpm; fp1 = fopen(IN_FILE1,"rb"); fp2 = fopen(IN_FILE2,"rb"); fpm = fopen(OUT_FILE,"wb"); short data1,data2,date_mix; int ret1,ret2; char sourseFile[10][2]; while(1) { ret1 = fread(&data1,2,1,fp1); ret2 = fread(&data2,2,1,fp2); *(short*) sourseFile[0] = data1; *(short*) sourseFile[1] = data2; if(ret1>0 && ret2>0) { Mix(sourseFile,2,(char *)&date_mix); /* if( data1 < 0 && data2 < 0) date_mix = data1+data2 - (data1 * data2 / -(pow(2,16-1)-1)); else date_mix = data1+data2 - (data1 * data2 / (pow(2,16-1)-1));*/ if(date_mix > pow(2,16-1) || date_mix < -pow(2,16-1)) printf("mix error\n"); } else if( (ret1 > 0) && (ret2==0)) { date_mix = data1; } else if( (ret2 > 0) && (ret1==0)) { date_mix = data2; } else if( (ret1 == 0) && (ret2 == 0)) { break; } fwrite(&date_mix,2,1,fpm); } fclose(fp1); fclose(fp2); fclose(fpm); printf("Done!\n"); }