網站首頁 編程語言 正文
PCM(Pulse Code Modulation)也被稱為脈沖編碼調制,是數字通信的編碼方式之一。PCM中的聲音數據沒有被壓縮,它將輸入的模擬信號進行采樣、量化和編碼,用二進制進行編碼的數來代表模擬信號的幅度,即標準的數字音頻數據。
采樣轉換方式參考下圖進行了解:
采樣率
采樣率表示音頻信號每秒的數字快照數。該速率決定了音頻文件的頻率范圍。采樣率越高,數字波形的形狀越接近原始模擬波形。低采樣率會限制可錄制的頻率范圍,這可導致錄音表現原始聲音的效果不佳。一般數字音頻常用的采樣率電話頻率8kHz、CD頻率44.1kHz、DVD頻率48kHz。
位深度
位深度決定動態范圍。采樣聲波時,為每個采樣指定最接近原始聲波振幅的振幅值。較高的位深度可提供更多可能的振幅值,產生更大的動態范圍、更低的噪聲基準和更高的保真度。普通的CD是16-bit。
通道
通道個數。常見的音頻有立體聲(stereo)和單聲道(mono)兩種類型,立體聲包含左聲道和右聲道。另外還有環繞立體聲等其它不太常用的類型。
Sign
表示樣本數據是否是有符號位,比如用一字節表示的樣本數據,有符號的話表示范圍為-128 ~ 127,無符號是0 ~ 255。
字節序
字節序是little-endian還是big-endian。通常均為little-endian
PCM信號的兩個重要指標是采樣頻率和量化精度,當在播放音樂時,應用程序從存儲介質中讀取音頻數據(MP3、WMA、AAC等),經過解碼后,最終送到音頻驅動程序中的就是PCM數據,反過來,在錄音時,音頻驅動不停地把采樣所得的PCM數據送回給應用程序,由應用程序完成壓縮、存儲等任務。下面我們展開介紹下PCM音頻的存儲及操作
PCM音頻數據存儲方式
如果是單聲道的音頻文件,采樣數據按時間的先后順序依次存入(有的時候也會采用LRLRLR方式存儲,只是另一個聲道的數據為0),如果是雙聲道的話就按照LRLRLR的方式存儲,存儲的時候與字節序有關。
big-endian模式如下圖所示:
PCM開發實戰
分離雙聲道PCM音頻數據左右聲道的數據
按照雙聲道的LRLRLR的PCM音頻數據可以通過將它們交叉的讀出來的方式來分離左右聲道的數據。
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降低某個聲道的音量
一般來說 PCM 數據中的波形幅值越大,代表音量越大,對于 PCM 音頻數據而言,它的幅值(即該采樣點采樣值的大小)代表音量的大小。如果我們需要降低某個聲道的音量,可以通過減小某個聲道的數據的值來實現降低某個聲道的音量。
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); // 一次讀取一個sample,因為是2聲道,所以是4字節
while ( !feof( fp_in ) ){
fread( sample, 1, 4, fp_in );
short* sample_num = ( short* )sample; // 轉成左右聲道兩個short數據
*sample_num = *sample_num / 2; // 左聲道數據減半
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 的取樣值之后,將其轉成了 C 語言中的一個 short 類型的變量。將該數值除以 2 之后寫回到了 PCM 文件中。?
將PCM16LE雙聲道音頻采樣數據的聲音速度提高一倍
下面函數可以通過抽象的方式將PCM16LE雙聲道數據的速度提高一倍,采樣左右聲道按奇(偶)數點的樣值的方式,函數的代碼如下所示:
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;
}
原文鏈接:https://blog.csdn.net/jh1988abc/article/details/122714920
相關推薦
- 2022-04-14 Python之OptionParser模塊使用詳解_python
- 2022-07-28 docker容器間進行數據共享的三種實現方式_docker
- 2023-04-08 Python實現將一段話txt生成字幕srt文件_python
- 2023-02-14 React?useCallback使用教程_React
- 2022-10-10 react使用axios實現上傳下載功能_React
- 2022-10-01 Qt+FFMPEG實現循環解碼詳解_C 語言
- 2022-10-06 使用pip下載時提示"You?are?using?pip?version?8.1.1,?howeve
- 2022-07-01 c++詳細講解構造函數的拷貝流程_C 語言
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支