1. 程式人生 > >pcm原始音訊採集率轉換

pcm原始音訊採集率轉換

pcm介紹

pcm也被稱為 脈碼編碼調製,是音訊中沒經過壓縮的原始資料。
在聲音採集中經過抽樣,量化,最後編碼。
取樣:對聲音進行一定頻率的採集,頻率越高,間隔時間越小,聲音更接近真實。常用的取樣率有8khz,16khz,22.05KHz、44.1KHz、48KHz等。
量化就是對每個採集的資料用數字訊號來表示聲音的振幅。如我可以用-10表示波谷,10表示波峰。也就是20個量化值來表示一段音樂。當然也可以用100個值表示,這樣分得更細,資料更精確。通常量化用一個char 8位表示(0-255),也有short16位(-32767-32767),32位等。
音訊資料在儲存中就是通過一個個量化資料儲存8/16位,8/16位,8/16位等
圖片來自網路


音訊資料還有單聲道和雙聲道的區別,其實就是同一時間採集一次還是兩次的區別
各種格式資料儲存如下
圖片來自網路

採集率的轉換

由上面知道,採集率就是單位時間採集資料次數的不同,如8khz和16khz。一秒採集了8k次和16k次。這樣16k轉換為8k,就是將16k降為8k,也就是每採集的兩次資料變為1次。(我採用兩個資料求平均除以2)
同理,8k變為16k升頻。將8k的每個資料變為兩個(後一個數據減去前一個數據除以2,加上前一個數據)
其他8k轉32k,32k轉換為8k那些同理。

/*  @breaf   用於pcm音訊採集率的轉換
	@param   bit[in],輸入檔案和輸出檔案的取樣位數
	@param   sourcefile[in],原始檔名
	@param   sou_rate[in],原始檔的採集率
	@param   disfile[out],目標檔名
	@param   dis_rate[in],目標檔案的採集率
	@return  0成功,-1出錯
	*/
void pcm_rate_trans(int bit,char * sourcefile,int sou_rate,char *disfile,int dis_rate ) { FILE *fp_sou; FILE *fp_dis; fopen_s(&fp_sou, sourcefile, "rb+"); fopen_s(&fp_dis,disfile, "wb+"); if (fp_sou==NULL|| fp_dis==NULL) { printf("error open!\n"); } int rate_len = sou_rate /
dis_rate; //減小取樣率 if (rate_len > 0) { short tempRead = 0; short tempSum = 0; int flag = 0; while (!feof(fp_sou)) { if (fread(&tempRead, bit/8, 1, fp_sou) > 0) { tempSum = tempSum + tempRead; // 求和 flag++; if (flag == rate_len) { flag = 0; tempSum = tempSum / rate_len; fwrite(&tempSum,bit/8, 1, fp_dis); tempSum = 0; } } } } //增大采樣率 else { rate_len = dis_rate/ sou_rate ; int tempRead1; int tempRead2; int tempSum; int tempWrite; int flag; while (!feof(fp_sou)) { if (fread(&tempRead1,bit/8, 1, fp_sou) >0&& fread(&tempRead2, bit / 8, 1, fp_sou) >0) { // tempSum = *((short *)&tempRead +1)-*(short *)&tempRead;//波距離 tempSum = tempRead2 - tempRead1; flag = rate_len; tempWrite =tempRead1; do { tempWrite += tempSum / rate_len; fwrite(&tempWrite, bit/8, 1, fp_dis); } while (--flag!=0); fseek(fp_sou, -1L*bit/8, SEEK_CUR); } } } fclose(fp_sou); fclose(fp_dis); }