pcm原始音訊採集率轉換
阿新 • • 發佈:2018-12-28
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);
}