91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

深入理解PCM:從底層代碼到音頻開發(fā)實(shí)戰(zhàn)

jf_44130326 ? 來源:Linux1024 ? 2026-02-05 13:57 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一、什么是PCM?音頻世界的"二進(jìn)制語言"

當(dāng)我們播放音樂、錄制語音時(shí),設(shè)備背后正在進(jìn)行一場"模擬與數(shù)字"的轉(zhuǎn)換游戲。PCMPulse Code Modulation,脈沖編碼調(diào)制)就是這場游戲的核心規(guī)則——它是將模擬音頻信號(如人聲、樂器聲)轉(zhuǎn)換為數(shù)字信號的標(biāo)準(zhǔn)方法,也是所有數(shù)字音頻的基礎(chǔ)。

wKgZO2kajD2Afz-oAAA4oTD7u4g223.png

PCM工作原理可以拆解為三步:

1.采樣:按固定時(shí)間間隔測量模擬信號的振幅(如44.1kHz采樣率即每秒測量44100次);

2.量化:將采樣得到的振幅值轉(zhuǎn)換為有限位的數(shù)字(如16位量化即振幅范圍分為65536個(gè)等級);

3.編碼:將量化后的數(shù)字以二進(jìn)制形式存儲(如16位量化的每個(gè)采樣點(diǎn)用2字節(jié)表示)。

關(guān)鍵參數(shù):

?采樣率(Rate:每秒采樣次數(shù)(如44100Hz、48000Hz);

?位深(Sample Bits:每個(gè)采樣點(diǎn)的量化位數(shù)(如16位、24位);

?通道數(shù)(Channels:單聲道(1)、立體聲(2)等;

?格式(Format:數(shù)據(jù)存儲方式(如S16_LE表示16位有符號小端模式)。

二、pcm.c代碼解析:音頻設(shè)備交互的"橋梁"

我們拿到的pcm.c是基于Linux TinyALSA庫的PCM設(shè)備操作實(shí)現(xiàn),核心功能是用戶態(tài)程序與內(nèi)核音頻驅(qū)動(dòng)的交互。下面梳理其核心流程與關(guān)鍵函數(shù):

1.核心結(jié)構(gòu)體:PCM設(shè)備的"身份證"

wKgZO2kajD2AJcamAAB-nO4u5a0371.png

structpcm{ intfd;         // 設(shè)備文件描述符(如/dev/snd/pcmC0D0p) unsignedintflags;   // 標(biāo)志(如PCM_IN/PCM_OUT表示輸入/輸出,PCM_MMAP表示內(nèi)存映射模式) intrunning:1;     // 運(yùn)行狀態(tài)標(biāo)記 intprepared:1;     // 準(zhǔn)備狀態(tài)標(biāo)記 unsignedintbuffer_size;// 緩沖區(qū)大?。▎挝唬簬?/span> structpcm_configconfig;// 音頻參數(shù)配置(采樣率、格式等) // ... 其他成員(mmap相關(guān)、錯(cuò)誤信息等)};

struct pcm是整個(gè)邏輯的核心,封裝了PCM設(shè)備的狀態(tài)、配置和底層交互信息。

2.核心流程:從打開到關(guān)閉的生命周期

wKgZO2kajD2AZw87AAAS_Xh-UmM705.png

wKgZO2kajD2AdxvJAAAdBysp080275.png

1)打開設(shè)備:pcm_open()

structpcm*pcm_open(unsignedintcard,unsignedintdevice,          unsignedintflags,structpcm_config *config);

?作用:打開指定的PCM設(shè)備(如/dev/snd/pcmC1D0p,C0表示第0塊聲卡,D0表示第0個(gè)設(shè)備,p表示播放);

?關(guān)鍵步驟

a.打開設(shè)備文件(open("/dev/snd/pcmC..."));

b.配置硬件參數(shù)(SNDRV_PCM_IOCTL_HW_PARAMS):設(shè)置格式、采樣率、通道數(shù)等;

c.配置軟件參數(shù)(SNDRV_PCM_IOCTL_SW_PARAMS):設(shè)置緩沖區(qū)閾值、邊界等;

d.初始化內(nèi)存映射(如果使用PCM_MMAP模式)。

2)數(shù)據(jù)讀寫:兩種模式

?讀寫模式(非MMAP

?播放:pcm_write()通過SNDRV_PCM_IOCTL_WRITEI_FRAMES向設(shè)備寫入數(shù)據(jù);

?錄制:pcm_read()通過SNDRV_PCM_IOCTL_READI_FRAMES從設(shè)備讀取數(shù)據(jù)。

?內(nèi)存映射模式(MMAP

?直接映射設(shè)備緩沖區(qū)到用戶態(tài)(mmap()),通過pcm_mmap_write()/pcm_mmap_read()高效傳輸;

?核心是通過pcm_mmap_begin()獲取緩沖區(qū)位置,pcm_mmap_commit()更新指針,減少內(nèi)核態(tài)與用戶態(tài)拷貝。

3)狀態(tài)控制:pcm_prepare()/pcm_start()/pcm_stop()

?pcm_prepare():準(zhǔn)備設(shè)備(重置狀態(tài),為啟動(dòng)做準(zhǔn)備);

?pcm_start():啟動(dòng)設(shè)備(開始音頻傳輸);

?pcm_stop():停止設(shè)備(中斷傳輸,重置狀態(tài))。

4)關(guān)閉設(shè)備:pcm_close()

釋放資源(關(guān)閉文件描述符、解除內(nèi)存映射、釋放結(jié)構(gòu)體)。

3.錯(cuò)誤處理:音頻問題的"預(yù)警器"

代碼中大量使用oops()函數(shù)記錄錯(cuò)誤信息(如設(shè)備打開失敗、參數(shù)設(shè)置無效),并通過pcm_get_error()暴露給上層。常見錯(cuò)誤包括:

?EPIPE:播放時(shí)緩沖區(qū)下溢(underrun),即數(shù)據(jù)供應(yīng)不及時(shí);

?EINVAL:參數(shù)無效(如不支持的采樣率);

?EBUSY:設(shè)備被占用。

三、初學(xué)者為什么要關(guān)注這個(gè)文件?

pcm.c音頻開發(fā)的"入門鑰匙",它能幫你理解:

1.用戶態(tài)與內(nèi)核的交互:如何通過ioctl()ALSA驅(qū)動(dòng)通信(如SNDRV_PCM_IOCTL_HW_PARAMS);

2.音頻參數(shù)的意義:采樣率、位深等參數(shù)如何影響硬件行為(如pcm_format_to_bits()轉(zhuǎn)換位深);

3.實(shí)時(shí)性的重要性:音頻傳輸對延遲敏感,pcm_wait()mmap等機(jī)制如何保證實(shí)時(shí)性;

4.錯(cuò)誤處理的邏輯:如何應(yīng)對緩沖區(qū)溢出/下溢等常見問題(如pcm_write()中的underrun重試)。

四、Linux音頻調(diào)試:pcm.c能幫你解決什么問題?

實(shí)際開發(fā)中,音頻問題(雜音、卡頓、無聲)往往可以通過分析pcm.c的邏輯定位根源。

案例1:播放時(shí)有雜音,格式不匹配

現(xiàn)象:播放音頻時(shí)出現(xiàn)爆破音或雜音,無報(bào)錯(cuò)但音質(zhì)異常。

排查

1.檢查pcm_format_to_alsa():確認(rèn)應(yīng)用使用的格式(如PCM_FORMAT_S16_LE)是否正確映射到ALSA格式(SNDRV_PCM_FORMAT_S16_LE);

2.查看pcm_params_format_test():驗(yàn)證設(shè)備是否支持當(dāng)前格式(通過掩碼檢測format_lookup)。

結(jié)論:若設(shè)備不支持指定格式,會默認(rèn)使用S16_LE,可能導(dǎo)致數(shù)據(jù)解析錯(cuò)誤,需修改struct pcm_configformat字段。

案例2:播放卡頓,緩沖區(qū)設(shè)置不合理

現(xiàn)象:音頻播放斷斷續(xù)續(xù),頻繁出現(xiàn)underrun(下溢)。

排查

1.查看pcm_open()中的buffer_size計(jì)算:buffer_size = period_count * period_size,緩沖區(qū)過小會導(dǎo)致數(shù)據(jù)供應(yīng)不及時(shí);

2.分析pcm_mmap_avail():通過hw_ptr(硬件指針)和appl_ptr(應(yīng)用指針)的差值,判斷是否緩沖區(qū)不足;

3.調(diào)整sw_params中的avail_min(最小可用幀數(shù)):增大閾值減少頻繁喚醒。

結(jié)論:增大period_countperiod_size可增加緩沖區(qū)容量,緩解卡頓。

案例3:設(shè)備無法打開,權(quán)限或占用問題

現(xiàn)象:調(diào)用pcm_open()返回失敗,錯(cuò)誤信息為"cannot open device"。

排查

1.檢查pcm_open()中設(shè)備路徑:/dev/snd/pcmC%uD%u%c,確認(rèn)聲卡(card)和設(shè)備(device)編號正確;

2.查看open()調(diào)用的重試邏輯:代碼中會重試50次(每次20ms),若仍失敗可能是設(shè)備被占用(如其他進(jìn)程已打開);

3.檢查權(quán)限:/dev/snd/pcm*需音頻組權(quán)限(如audio用戶組)。

五、總結(jié):從代碼到實(shí)戰(zhàn)的音頻開發(fā)之路

pcm.c看似是一個(gè)底層文件,實(shí)則是理解Linux音頻系統(tǒng)的"窗口":它連接了應(yīng)用層的音頻需求與內(nèi)核驅(qū)動(dòng)的硬件能力,藏著音頻參數(shù)、實(shí)時(shí)傳輸、錯(cuò)誤處理的核心邏輯。

對于初學(xué)者,建議從這幾個(gè)方向入手:

1.跟蹤pcm_open()的參數(shù)配置流程,理解每個(gè)音頻參數(shù)的作用;

2.對比pcm_write()pcm_mmap_write(),分析兩種傳輸模式的效率差異;

3.結(jié)合調(diào)試案例,嘗試修改緩沖區(qū)大小、采樣率等參數(shù),觀察效果變化。

掌握了pcm.c,你就掌握了數(shù)字音頻在Linux中的"傳輸密碼",無論是開發(fā)播放器、錄音應(yīng)用還是調(diào)試音頻驅(qū)動(dòng),都能更游刃有余。

附錄:流程圖與腦圖

1. PCM設(shè)備操作流程圖

wKgZO2kajD2AFIHIAAHK3RUVML8700.jpg

2.核心知識腦圖

wKgZO2kajD6AHSavAAJZ1QR2EJQ149.png


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • PCM
    PCM
    +關(guān)注

    關(guān)注

    1

    文章

    212

    瀏覽量

    55790
  • 數(shù)字音頻
    +關(guān)注

    關(guān)注

    9

    文章

    224

    瀏覽量

    68204
  • 模擬信號
    +關(guān)注

    關(guān)注

    8

    文章

    1232

    瀏覽量

    54672
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    【書籍評測活動(dòng)NO.25】深入理解FFmpeg,帶你FFmpeg入門精通

    ,涵蓋音視頻基礎(chǔ)知識、FFmpeg參數(shù)解析、API使用、內(nèi)部組件的開發(fā)定制 行業(yè)大咖審校,多名業(yè)界專家與學(xué)者作序推薦 詳細(xì)解讀實(shí)際應(yīng)用與開發(fā)案例,幫助讀者深入理解FFmpeg 大咖推薦 我
    發(fā)表于 11-15 14:26

    深入理解Android

    深入理解Android
    發(fā)表于 08-20 15:30

    深入理解和實(shí)現(xiàn)RTOS_連載

    了解和掌握RTOS的多任務(wù)機(jī)制。深入理解和實(shí)現(xiàn)RTOS_連載4_多任務(wù)機(jī)制實(shí)現(xiàn)本篇將詳細(xì)介紹TROCHILI RTOS 多任務(wù)機(jī)制的實(shí)現(xiàn),內(nèi)容很詳細(xì)、很豐富,涉及了大量RTOS底層實(shí)現(xiàn)。建議讀者參考實(shí)際代碼
    發(fā)表于 05-29 11:20

    深入理解和實(shí)現(xiàn)RTOS_連載

    多任務(wù)機(jī)制實(shí)現(xiàn)本篇將詳細(xì)介紹TROCHILI RTOS 多任務(wù)機(jī)制的實(shí)現(xiàn),內(nèi)容很詳細(xì)、很豐富,涉及了大量RTOS底層實(shí)現(xiàn)。建議讀者參考實(shí)際代碼,那里有更詳細(xì)的注釋,而且是全中文的。深入理解和實(shí)現(xiàn)
    發(fā)表于 05-30 01:02

    分享高性能Android應(yīng)用開發(fā)超清版PDF

    ;amp;ckook《深入理解Android:Wi-Fi、nfc和gps卷》Android Studio實(shí)戰(zhàn)快速高效地構(gòu)建Android應(yīng)用Android編程權(quán)威指南Android第一行代碼
    發(fā)表于 08-13 10:40

    深入理解lte-a

    深入理解LTE-A
    發(fā)表于 02-26 10:21

    深入理解STM32

    時(shí)鐘系統(tǒng)是處理器的核心,所以在學(xué)習(xí)STM32所有外設(shè)之前,認(rèn)真學(xué)習(xí)時(shí)鐘系統(tǒng)是必要的,有助于深入理解STM32。下面是網(wǎng)上找的一個(gè)STM32時(shí)鐘框圖,比《STM32中文參考手冊》里面的是中途看起來清晰一些:重要的時(shí)鐘:PLLCLK,SYSCLK,HCKL,PCLK1,..
    發(fā)表于 08-12 07:46

    對棧的深入理解

    為什么要深入理解棧?做C語言開發(fā)如果棧設(shè)置不合理或者使用不對,棧就會溢出,溢出就會遇到無法預(yù)測亂飛現(xiàn)象。所以對棧的深入理解是非常重要的。注:動(dòng)畫如果看不清楚可以電腦看更清晰啥是棧先來看一段動(dòng)畫:沒有
    發(fā)表于 02-15 07:01

    為什么要深入理解

    [導(dǎo)讀] 從這篇文章開始,將會不定期更新關(guān)于嵌入式C語言編程相關(guān)的個(gè)人認(rèn)為比較重要的知識點(diǎn),或者踩過的坑。為什么要深入理解棧?做C語言開發(fā)如果棧設(shè)置不合理或者使用不對,棧就會溢出,溢出就會遇到無法
    發(fā)表于 02-15 06:09

    深入理解Android之資源文件

    深入理解Android之資源文件
    發(fā)表于 01-22 21:11 ?22次下載

    深入理解Android》文前

    深入理解Android》文前
    發(fā)表于 03-19 11:23 ?0次下載

    深入理解Android:卷I》

    深入理解Android:卷I》
    發(fā)表于 03-19 11:23 ?0次下載

    深入理解Android網(wǎng)絡(luò)編程

    深入理解Android網(wǎng)絡(luò)編程
    發(fā)表于 03-19 11:26 ?1次下載

    深入理解MOS管電子版資源下載

    深入理解MOS管電子版資源下載
    發(fā)表于 07-09 09:43 ?0次下載

    深入理解LED開發(fā)過程

    不知道你是否想過,一個(gè)LED燈點(diǎn)亮過程的本質(zhì)是什么。當(dāng)你是一個(gè)小白的時(shí)候,點(diǎn)亮一個(gè)LED燈,IDE都會幫你做好所有的事情,你只需要點(diǎn)擊一下編譯即可。但是,當(dāng)你成長到一定程度時(shí),就需要好好想想,一個(gè)LED的點(diǎn)亮,其實(shí)是對單片機(jī)中背后原理機(jī)制真正的深入理解。今天我就帶你,來深入理解
    發(fā)表于 12-22 19:08 ?9次下載
    <b class='flag-5'>深入理解</b>LED<b class='flag-5'>開發(fā)</b>過程