最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文帶你深入了解C++中音頻PCM數(shù)據(jù)

 更新時(shí)間:2023年02月10日 10:25:50   作者:很久沒(méi)安靜的回憶了  
PCM(Pulse Code Modulation)也被稱為脈沖編碼調(diào)制,是數(shù)字通信的編碼方式之一。這篇文章主要和大家聊聊C++中音頻PCM數(shù)據(jù)的相關(guān)操作,需要的可以參考一下

PCM(Pulse Code Modulation)也被稱為脈沖編碼調(diào)制,是數(shù)字通信的編碼方式之一。PCM中的聲音數(shù)據(jù)沒(méi)有被壓縮,它將輸入的模擬信號(hào)進(jìn)行采樣、量化和編碼,用二進(jìn)制進(jìn)行編碼的數(shù)來(lái)代表模擬信號(hào)的幅度,即標(biāo)準(zhǔn)的數(shù)字音頻數(shù)據(jù)。

采樣轉(zhuǎn)換方式參考下圖進(jìn)行了解:

采樣率

采樣率表示音頻信號(hào)每秒的數(shù)字快照數(shù)。該速率決定了音頻文件的頻率范圍。采樣率越高,數(shù)字波形的形狀越接近原始模擬波形。低采樣率會(huì)限制可錄制的頻率范圍,這可導(dǎo)致錄音表現(xiàn)原始聲音的效果不佳。一般數(shù)字音頻常用的采樣率電話頻率8kHz、CD頻率44.1kHz、DVD頻率48kHz。

位深度

位深度決定動(dòng)態(tài)范圍。采樣聲波時(shí),為每個(gè)采樣指定最接近原始聲波振幅的振幅值。較高的位深度可提供更多可能的振幅值,產(chǎn)生更大的動(dòng)態(tài)范圍、更低的噪聲基準(zhǔn)和更高的保真度。普通的CD是16-bit。

通道

通道個(gè)數(shù)。常見(jiàn)的音頻有立體聲(stereo)和單聲道(mono)兩種類型,立體聲包含左聲道和右聲道。另外還有環(huán)繞立體聲等其它不太常用的類型。

Sign

表示樣本數(shù)據(jù)是否是有符號(hào)位,比如用一字節(jié)表示的樣本數(shù)據(jù),有符號(hào)的話表示范圍為-128 ~ 127,無(wú)符號(hào)是0 ~ 255。

字節(jié)序

字節(jié)序是little-endian還是big-endian。通常均為little-endian

PCM信號(hào)的兩個(gè)重要指標(biāo)是采樣頻率和量化精度,當(dāng)在播放音樂(lè)時(shí),應(yīng)用程序從存儲(chǔ)介質(zhì)中讀取音頻數(shù)據(jù)(MP3、WMA、AAC等),經(jīng)過(guò)解碼后,最終送到音頻驅(qū)動(dòng)程序中的就是PCM數(shù)據(jù),反過(guò)來(lái),在錄音時(shí),音頻驅(qū)動(dòng)不停地把采樣所得的PCM數(shù)據(jù)送回給應(yīng)用程序,由應(yīng)用程序完成壓縮、存儲(chǔ)等任務(wù)。下面我們展開(kāi)介紹下PCM音頻的存儲(chǔ)及操作

PCM音頻數(shù)據(jù)存儲(chǔ)方式

如果是單聲道的音頻文件,采樣數(shù)據(jù)按時(shí)間的先后順序依次存入(有的時(shí)候也會(huì)采用LRLRLR方式存儲(chǔ),只是另一個(gè)聲道的數(shù)據(jù)為0),如果是雙聲道的話就按照LRLRLR的方式存儲(chǔ),存儲(chǔ)的時(shí)候與字節(jié)序有關(guān)。

big-endian模式如下圖所示:

PCM開(kāi)發(fā)實(shí)戰(zhàn)

分離雙聲道PCM音頻數(shù)據(jù)左右聲道的數(shù)據(jù)

按照雙聲道的LRLRLR的PCM音頻數(shù)據(jù)可以通過(guò)將它們交叉的讀出來(lái)的方式來(lái)分離左右聲道的數(shù)據(jù)。

int pcm_s16le_split(const char* file, const char* out_lfile, const char* out_rfile) {
     FILE *fp = fopen(file, "rb+");
     if (fp == NULL) {
         printf("open %s failed\n", file);
         return -1;
     }
     FILE *fp1 = fopen(out_lfile, "wb+");
     if (fp1 == NULL) {
         printf("open %s failed\n", out_lfile);
         return -1;
     }
     FILE *fp2 = fopen(out_rfile, "wb+");
     if (fp2 == NULL) {
         printf("open %s failed\n", out_rfile);
         return -1;
     }
     char * sample = (char *)malloc(4);
     while(!feof(fp)) {
         fread(sample, 1, 4, fp);
         //L
         fwrite(sample, 1, 2, fp1);
         //R
         fwrite(sample + 2, 1, 2, fp2);
     }
     free(sample);
     fclose(fp);
     fclose(fp1);
     fclose(fp2);
     return 0;
 }

PCM降低某個(gè)聲道的音量

一般來(lái)說(shuō) PCM 數(shù)據(jù)中的波形幅值越大,代表音量越大,對(duì)于 PCM 音頻數(shù)據(jù)而言,它的幅值(即該采樣點(diǎn)采樣值的大?。┐硪袅康拇笮?。如果我們需要降低某個(gè)聲道的音量,可以通過(guò)減小某個(gè)聲道的數(shù)據(jù)的值來(lái)實(shí)現(xiàn)降低某個(gè)聲道的音量。

int pcm16le_half_volume_left( char *url ) {
    FILE *fp_in = fopen( url, "rb+" );
    if (fp_in == NULL) {
         printf("open %s failed\n", infile);
         return -1;
     }
    FILE *fp_out = fopen( "output_half_left.pcm", "wb+" );
    if (fp_out == NULL) {
         printf("open %s failed\n", outfile);
         return -1;
     }
    unsigned char *sample = ( unsigned char * )malloc(4); // 一次讀取一個(gè)sample,因?yàn)槭?聲道,所以是4字節(jié) 
    while ( !feof( fp_in ) ){
        fread( sample, 1, 4, fp_in );
        short* sample_num = ( short* )sample; // 轉(zhuǎn)成左右聲道兩個(gè)short數(shù)據(jù)
        *sample_num = *sample_num / 2; // 左聲道數(shù)據(jù)減半
        fwrite( sample, 1, 2, fp_out ); // L
        fwrite( sample + 2, 1, 2, fp_out ); // R
    }
    free( sample );
    fclose( fp_in );
    fclose( fp_out );
    return 0;
}

上述程序做的事情是:在讀出左聲道的 2 Byte 的取樣值之后,將其轉(zhuǎn)成了 C 語(yǔ)言中的一個(gè) short 類型的變量。將該數(shù)值除以 2 之后寫回到了 PCM 文件中。 

將PCM16LE雙聲道音頻采樣數(shù)據(jù)的聲音速度提高一倍

下面函數(shù)可以通過(guò)抽象的方式將PCM16LE雙聲道數(shù)據(jù)的速度提高一倍,采樣左右聲道按奇(偶)數(shù)點(diǎn)的樣值的方式,函數(shù)的代碼如下所示:

int simplest_pcm16le_doublespeed(char *url){
    FILE *fp=fopen(url,"rb+");
    if (fp == NULL) {
         printf("open %s failed\n", file);
         return -1;
     }
    FILE *fp1=fopen("output_doublespeed.pcm","wb+");
    if (fp1 == NULL) {
         printf("open %s failed\n", outFile);
         return -1;
     }
    int cnt=0;
 
    unsigned char *sample=(unsigned char *)malloc(4);
 
    while(!feof(fp)){
 
        fread(sample,1,4,fp);
 
        if(cnt&1!=0){
            //L
            fwrite(sample,1,2,fp1);
            //R
            fwrite(sample+2,1,2,fp1);
        }
        cnt++;
    }
    printf("Sample Cnt:%d\n",cnt);
 
    free(sample);
    fclose(fp);
    fclose(fp1);
    return 0;
}

到此這篇關(guān)于一文帶你深入了解C++中音頻PCM數(shù)據(jù)的文章就介紹到這了,更多相關(guān)C++音頻PCM內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

韶关市| 遵义市| 双牌县| 白朗县| 桦川县| 信丰县| 沁源县| 高唐县| 泰州市| 永平县| 成安县| 金沙县| 喀喇| 青龙| 陆丰市| 辽源市| 梁山县| 喀什市| 锦州市| 读书| 隆昌县| 白沙| 荣成市| 漳浦县| 新化县| 云安县| 绵竹市| 唐河县| 桂林市| 汪清县| 沈阳市| 伊吾县| 温宿县| 五莲县| 威远县| 砀山县| 平乡县| 河间市| 汝州市| 海伦市| 莱芜市|