日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

音频系统,Alsa 里面的buff 是怎么计算的?

發布時間:2023/12/20 windows 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 音频系统,Alsa 里面的buff 是怎么计算的? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

相關文章

(干貨)Ai音箱和Linux音頻驅動小談
Linux ALSA 圖解
我在MTK平臺下調試音頻ALSA

我們知道聲音是模擬信號,模擬信號轉成數字信號就一定有大小,既然有大小,那我們就需要開辟內存來保存這些數據。

---- 我們知道,視頻流的一幀就是一張圖像 ------ 但是音頻不一樣,音頻的一幀不能表示是一句話,因為你不知道一個人說話的時間長度。

java讀取音頻代碼

int?bufferLen?=?mSampleRateInHz?*?channels?*?2?/?10;?//?100ms?data//int?bufferLen?=?2048;if?((channels?==?1)?&&?(mSampleRateInHz?==?32000)?&&?(mAudioSource?==?6)?&&?(mMaxChannels?>?0)){?//?get?raw?databufferLen?=?16000?*?mMaxChannels?*?2?/?10;?//?100ms?data}byte[]?buffer?=?new?byte[bufferLen];mAudioRecorder?=?new?AudioRecord(mAudioSource,?mSampleRateInHz,?mChannelConfig,AudioFormat.ENCODING_PCM_16BIT,?bufferLen?*?10);?//1?sec?bufferwhile(true){size?=?mAudioRecorder.read(buffer,?0,?bufferLen);?//100ms}

tinycap 里面的 pcm_read 代碼

int?pcm_read(struct?pcm?*pcm,?void?*data,?unsigned?int?count) {struct?snd_xferi?x;if?(!(pcm->flags?&?PCM_IN))return?-EINVAL;x.buf?=?data;x.frames?=?count?/?(pcm->config.channels?*pcm_format_to_bits(pcm->config.format)?/?8);for?(;;)?{if?(!pcm->running)?{if?(pcm_start(pcm)?<?0)?{fprintf(stderr,?"start?error");return?-errno;}}if?(ioctl(pcm->fd,?SNDRV_PCM_IOCTL_READI_FRAMES,?&x))?{pcm->prepared?=?0;pcm->running?=?0;if?(errno?==?EPIPE)?{/*?we?failed?to?make?our?window?--?try?to?restart?*/pcm->underruns++;continue;}return?oops(pcm,?errno,?"cannot?read?stream?data");}return?0;} }

提煉下重點

我們在里面看的一個英文單詞 frames ,frames 相當一幀的數據。

----但是這個一幀跟視頻流里面的一張圖像又不是一個概念,這里的一幀相當于聲音里面的最小計量單位。

音頻幀圖解

解釋一下上面的圖片

假設我們使用的是一個立體聲 16位 16k的音頻流,不管是錄音還是播放都一樣,那么

  • 立體聲 = 2通道

  • 1次ADC轉換樣本數據是 16bits = 2bytes

  • 1個幀 代表 所有通道的ADC轉換數據。那么我們現在是雙通道,所以

    • 1幀 = (通道數) * (樣本大小bytes) = 2 * 2 = 4bytes

  • 為了能支持2 * 16k的采樣率,系統必須支持如下的速度

    • bsp_rate = (通道數) * (1個樣本長度) * (采樣率) = 1幀 * 采樣率 =

      2 * 2 *16k = 64000bytes/sec(秒)

假設現在 alsa每秒中斷DMA一次。那么我們每秒都需要64000bytes數據準備好,才能滿足一個 雙通道 16 位 16k的音頻流。

  • 如果半秒中斷一次,那么每次中斷就是 64000bytes/ 2 = 32000bytes

  • 如果我們100ms 產生一次中斷,那么每次中斷就是 64000bytes / 10 = 6400bytes

我們可以通過設置period size 來控制pcm中斷的產生。

反推一下
---- 如果我們設置一個16位雙通道16k的音頻流, 并且每次都有1600幀數據
---- 4 byte * 1600frams = 6400字節
---- 一次中斷會需要6400字節的數據
----那么他就是100ms中斷一次「看上面的推斷」

alsa會自己適應實際的buffer_size 和period_size,根據請求的通道數,和他們其他的一些屬性。

把音頻格式轉換成bits的代碼

unsigned?int?pcm_format_to_bits(enum?pcm_format?format) {switch?(format)?{case?PCM_FORMAT_S32_LE:case?PCM_FORMAT_S24_LE:return?32;case?PCM_FORMAT_S24_3LE:return?24;default:case?PCM_FORMAT_S16_LE:return?16;}; }

我們會使用這個函數拿到對應格式的音頻bit「正常是16bit 和 32bit」,但是,我們讀寫數據是字節對齊bytes對齊的,這也是我們看到很多地方有除以8這個操作的原因。

?x.buf?=?data;x.frames?=?count?/?(pcm->config.channels?*pcm_format_to_bits(pcm->config.format)?/?8);

測試的小程序

---- 用來錄音的測試程序

#include?<stdio.h>#define?UNUSED(x)?(void)(x)int?main(int?argc,?char?**argv)?{UNUSED(argc);UNUSED(argv);char?*cmd?=?"tinycap?/sdcard/1.pcm?-D?0?-d?3?-r?16000?-c?2?-b?16";char?buf[256];FILE?*fp?=?popen(cmd,?"r");for?(int?i=0;?i<16;?i++)?{int?result?=?fread(buf,?1,?sizeof(buf),?fp);printf("read?%d?bytes\n",?result);}pclose(fp);return?0; }

這個程序會打開聲卡 0 第 3 個pcm通路去錄音。
我們這里沒有設置「-p」這個屬性,加上這個屬性之后,就會知道在1秒內的中斷次數,從而知道1秒內的音頻大小了。當然了,我們不設置,也會有一個默認值的。

? 推薦閱讀:

? ??專輯|Linux文章匯總

? ??專輯|程序人生

? ??專輯|C語言

嵌入式Linux

微信掃描二維碼,關注我的公眾號?

總結

以上是生活随笔為你收集整理的音频系统,Alsa 里面的buff 是怎么计算的?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。