#include <stdio.h>
#include <stdint.h>
#include <alsa/asoundlib.h>
#define PERIOD_SIZE 128
#define BUFFER_SIZE (PERIOD_SIZE*8)
#define THRESHOLD_SIZE 0
typedef struct {
int16_t left;
int16_t right;
} PCM_FRAME;
// 打開alsa
static void* alsa_open(uint32_t rate){
snd_pcm_t *handle = NULL;
snd_pcm_hw_params_t *hw_params;
snd_pcm_sw_params_t *sw_params;
snd_pcm_hw_params_malloc(&hw_params);
snd_pcm_sw_params_malloc(&sw_params);
// 打開alsa
if(snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
return NULL;
}
// 取所有參數(shù)?還是設(shè)置所以參數(shù)默認(rèn)值?
if(snd_pcm_hw_params_any(handle, hw_params) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 設(shè)置頻率可重采樣?
if(snd_pcm_hw_params_set_rate_resample(handle, hw_params, 1) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 設(shè)置訪問模式
if(snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 設(shè)置格式
if(snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 設(shè)置聲道數(shù)
if(snd_pcm_hw_params_set_channels(handle, hw_params, 2) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 設(shè)置采樣頻率
if(snd_pcm_hw_params_set_rate_near(handle, hw_params, &rate, 0) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 設(shè)置環(huán)buffer大小,單位是幀
if(snd_pcm_hw_params_set_buffer_size(handle, hw_params, BUFFER_SIZE) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 設(shè)置周期大小,單位是幀
if(snd_pcm_hw_params_set_period_size(handle, hw_params, PERIOD_SIZE, 0) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 硬參數(shù)設(shè)置生效
if(snd_pcm_hw_params(handle, hw_params) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 取所有參數(shù)?還是設(shè)置所以參數(shù)默認(rèn)值?
if(snd_pcm_sw_params_current(handle, sw_params) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 設(shè)置開始回放的閾值,單位是幀
if(snd_pcm_sw_params_set_start_threshold(handle, sw_params, THRESHOLD_SIZE) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 軟參數(shù)設(shè)置生效
if(snd_pcm_sw_params(handle, sw_params) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
// 進(jìn)入準(zhǔn)備狀態(tài)
if(snd_pcm_prepare(handle) < 0){
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
snd_pcm_close(handle);
return NULL;
}
snd_pcm_sw_params_free(sw_params);
snd_pcm_hw_params_free(hw_params);
return handle;
}
// 回放
static int alsa_write(void *handle, void *buffer, int frameNum){
int err;
int ready = 0;
PCM_FRAME *frame = buffer;
do{
while((err = snd_pcm_writei(handle, frame+ready, frameNum-ready)) == -EAGAIN);
if(err > 0){
ready += err;
}else{
if(err == -EPIPE){
err = snd_pcm_prepare(handle);
if(err != 0) return -1;
}else{
return -2;
}
}
}while(ready < frameNum);
return ready;
}
// 關(guān)閉alsa
static void alsa_close(void *handle){
if(handle){
snd_pcm_drop(handle);
snd_pcm_close(handle);
}
}
代碼片段:ALSA回放
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 1.copy:@property(nonatomic, copy)NSString*<#string#>;2.st...
- 代碼片段 Xcode的代碼片段(Code Snippets)創(chuàng)建自定義的代碼片段,當(dāng)你重用這些代碼片段時(shí),會(huì)給你帶...
- “極客標(biāo)簽”是一個(gè)面向 Geek 的編程學(xué)習(xí)與資源分享網(wǎng)站,為用戶提供代碼學(xué)習(xí)、資源分享和在線調(diào)試服務(wù),依靠核心的...